14b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/*
24b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Copyright (C) 2013 The Android Open Source Project
34b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov *
44b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Licensed under the Apache License, Version 2.0 (the "License");
54b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * you may not use this file except in compliance with the License.
64b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * You may obtain a copy of the License at
74b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov *
84b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov *      http://www.apache.org/licenses/LICENSE-2.0
94b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov *
104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Unless required by applicable law or agreed to in writing, software
114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * distributed under the License is distributed on an "AS IS" BASIS,
124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * See the License for the specific language governing permissions and
144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * limitations under the License.
154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */
164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovpackage com.android.printspooler;
184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.app.Service;
204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.ComponentName;
214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.Intent;
22269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.os.AsyncTask;
23b4fda134761c9521a7e127db3806a07a18763b77Svetoslavimport android.os.Bundle;
244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.IBinder;
254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Message;
264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.ParcelFileDescriptor;
274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.RemoteException;
28a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.IPrintSpooler;
29a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.IPrintSpoolerCallbacks;
30835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganovimport android.print.IPrintSpoolerClient;
31269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PageRange;
324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.PrintAttributes;
33269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrintAttributes.Margins;
34269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrintAttributes.MediaSize;
35269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrintAttributes.Resolution;
36269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrintDocumentInfo;
372fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslavimport android.print.PrintJobId;
384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.PrintJobInfo;
39269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrintManager;
40269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrinterId;
41269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrinterInfo;
42a76233ae845da4bc9e3bcd89821701a747215e7bSvetoslavimport android.text.TextUtils;
43dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganovimport android.util.ArrayMap;
44269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.util.AtomicFile;
45835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganovimport android.util.Log;
464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.util.Slog;
47269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.util.Xml;
484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
49269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport com.android.internal.os.HandlerCaller;
50269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport com.android.internal.util.FastXmlSerializer;
514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
522fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslavimport libcore.io.IoUtils;
532fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav
54269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport org.xmlpull.v1.XmlPullParser;
55269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport org.xmlpull.v1.XmlPullParserException;
56269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport org.xmlpull.v1.XmlSerializer;
57269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
58269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.io.File;
59dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganovimport java.io.FileDescriptor;
60269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.io.FileInputStream;
61269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.io.FileNotFoundException;
62269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.io.FileOutputStream;
63269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.io.IOException;
64dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganovimport java.io.PrintWriter;
65269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.util.ArrayList;
66835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganovimport java.util.List;
67835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov
684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/**
694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Service for exposing some of the {@link PrintSpooler} functionality to
704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * another process.
714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */
724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovpublic final class PrintSpoolerService extends Service {
734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
74269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    private static final String LOG_TAG = "PrintSpoolerService";
75269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
76b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav    private static final boolean DEBUG_PRINT_JOB_LIFECYCLE = false;
77269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
78c6066799ad130140159230d14451b429eb828755Svetoslav    private static final boolean DEBUG_PERSISTENCE = false;
79269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
80269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    private static final boolean PERSISTNECE_MANAGER_ENABLED = true;
81269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
82835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov    private static final long CHECK_ALL_PRINTJOBS_HANDLED_DELAY = 5000;
83835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov
84dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov    private static final String PRINT_JOB_FILE_PREFIX = "print_job_";
85dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov
86269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    private static final String PRINT_FILE_EXTENSION = "pdf";
87269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
88269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    private static final Object sLock = new Object();
89269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
90269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    private final Object mLock = new Object();
91269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
92269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    private final List<PrintJobInfo> mPrintJobs = new ArrayList<PrintJobInfo>();
93269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
94269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    private static PrintSpoolerService sInstance;
95269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
96835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov    private IPrintSpoolerClient mClient;
974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
98269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    private HandlerCaller mHandlerCaller;
99269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
100269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    private PersistenceManager mPersistanceManager;
101269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
102269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    private NotificationController mNotificationController;
103269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
104269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    public static PrintSpoolerService peekInstance() {
105269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        synchronized (sLock) {
106269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            return sInstance;
107269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
108269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
1094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    @Override
1114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public void onCreate() {
1124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        super.onCreate();
113269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        mHandlerCaller = new HandlerCaller(this, getMainLooper(),
114269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                new HandlerCallerCallback(), false);
115269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
116269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        mPersistanceManager = new PersistenceManager();
117269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        mNotificationController = new NotificationController(PrintSpoolerService.this);
118269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
119269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        synchronized (mLock) {
120269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            mPersistanceManager.readStateLocked();
121269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            handleReadPrintJobsLocked();
122269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
123269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
124269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        synchronized (sLock) {
125269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            sInstance = this;
126269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
1274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
1284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    @Override
1304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public IBinder onBind(Intent intent) {
1317bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        return new PrintSpooler();
1324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
1334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
134dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov    @Override
135dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
136dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov        synchronized (mLock) {
137b67a637e60c356ab520050b2bd09a95ae47f3017Svetoslav            String prefix = (args.length > 0) ? args[0] : "";
138dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            String tab = "  ";
139dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov
140dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            pw.append(prefix).append("print jobs:").println();
141dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            final int printJobCount = mPrintJobs.size();
142dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            for (int i = 0; i < printJobCount; i++) {
143dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                PrintJobInfo printJob = mPrintJobs.get(i);
144dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                pw.append(prefix).append(tab).append(printJob.toString());
145dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                pw.println();
146dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            }
147dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov
148dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            pw.append(prefix).append("print job files:").println();
149dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            File[] files = getFilesDir().listFiles();
150dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            if (files != null) {
151dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                final int fileCount = files.length;
152dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                for (int i = 0; i < fileCount; i++) {
153dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                    File file = files[i];
154dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                    if (file.isFile() && file.getName().startsWith(PRINT_JOB_FILE_PREFIX)) {
155dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                        pw.append(prefix).append(tab).append(file.getName()).println();
156dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                    }
157dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                }
158dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            }
159dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov        }
160dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov    }
161dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov
162269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    private void sendOnPrintJobQueued(PrintJobInfo printJob) {
163269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        Message message = mHandlerCaller.obtainMessageO(
164269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                HandlerCallerCallback.MSG_ON_PRINT_JOB_QUEUED, printJob);
165269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        mHandlerCaller.executeOrSendMessage(message);
166269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
167269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
168269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    private void sendOnAllPrintJobsForServiceHandled(ComponentName service) {
169269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        Message message = mHandlerCaller.obtainMessageO(
170269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                HandlerCallerCallback.MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED, service);
171269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        mHandlerCaller.executeOrSendMessage(message);
172269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
173269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
174269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    private void sendOnAllPrintJobsHandled() {
175269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        Message message = mHandlerCaller.obtainMessage(
176269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                HandlerCallerCallback.MSG_ON_ALL_PRINT_JOBS_HANDLED);
177269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        mHandlerCaller.executeOrSendMessage(message);
178269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
179269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
180269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    private final class HandlerCallerCallback implements HandlerCaller.Callback {
181704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        public static final int MSG_SET_CLIENT = 1;
1827bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        public static final int MSG_ON_PRINT_JOB_QUEUED = 2;
1837bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        public static final int MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED = 3;
1847bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 4;
1857bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        public static final int MSG_CHECK_ALL_PRINTJOBS_HANDLED = 5;
1867bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        public static final int MSG_ON_PRINT_JOB_STATE_CHANGED = 6;
1874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        @Override
189269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        public void executeMessage(Message message) {
190835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            switch (message.what) {
191835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                case MSG_SET_CLIENT: {
192269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    synchronized (mLock) {
193269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        mClient = (IPrintSpoolerClient) message.obj;
194269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        if (mClient != null) {
195269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            Message msg = mHandlerCaller.obtainMessage(
196269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                                    HandlerCallerCallback.MSG_CHECK_ALL_PRINTJOBS_HANDLED);
197269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            mHandlerCaller.sendMessageDelayed(msg,
198269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                                    CHECK_ALL_PRINTJOBS_HANDLED_DELAY);
199269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        }
200835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                    }
201835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                } break;
202835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov
203835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                case MSG_ON_PRINT_JOB_QUEUED: {
204835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                    PrintJobInfo printJob = (PrintJobInfo) message.obj;
205835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                    if (mClient != null) {
206835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                        try {
207835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                            mClient.onPrintJobQueued(printJob);
208835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                        } catch (RemoteException re) {
209835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                            Slog.e(LOG_TAG, "Error notify for a queued print job.", re);
210835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                        }
211835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                    }
212835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                } break;
213835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov
214835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                case MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED: {
215835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                    ComponentName service = (ComponentName) message.obj;
216835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                    if (mClient != null) {
217835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                        try {
218835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                            mClient.onAllPrintJobsForServiceHandled(service);
219835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                        } catch (RemoteException re) {
220835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                            Slog.e(LOG_TAG, "Error notify for all print jobs per service"
221835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                                    + " handled.", re);
222835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                        }
223835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                    }
224835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                } break;
225835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov
226835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                case MSG_ON_ALL_PRINT_JOBS_HANDLED: {
227835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                    if (mClient != null) {
228835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                        try {
229835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                            mClient.onAllPrintJobsHandled();
230835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                        } catch (RemoteException re) {
231835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                            Slog.e(LOG_TAG, "Error notify for all print job handled.", re);
232835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                        }
233835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                    }
234835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                } break;
235835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov
236835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                case MSG_CHECK_ALL_PRINTJOBS_HANDLED: {
237269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    checkAllPrintJobsHandled();
238269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                } break;
239704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov
240704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                case MSG_ON_PRINT_JOB_STATE_CHANGED: {
241704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                    if (mClient != null) {
242dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                        PrintJobInfo printJob = (PrintJobInfo) message.obj;
243704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                        try {
244dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                            mClient.onPrintJobStateChanged(printJob);
245704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                        } catch (RemoteException re) {
246704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                            Slog.e(LOG_TAG, "Error notify for print job state change.", re);
247704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                        }
248704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                    }
249704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                } break;
2504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
2514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
2524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
253269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
254269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    public List<PrintJobInfo> getPrintJobInfos(ComponentName componentName,
255269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            int state, int appId) {
256269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        List<PrintJobInfo> foundPrintJobs = null;
257269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        synchronized (mLock) {
258269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            final int printJobCount = mPrintJobs.size();
259269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            for (int i = 0; i < printJobCount; i++) {
260269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                PrintJobInfo printJob = mPrintJobs.get(i);
261269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                PrinterId printerId = printJob.getPrinterId();
262269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                final boolean sameComponent = (componentName == null
263269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        || (printerId != null
264269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        && componentName.equals(printerId.getServiceName())));
265269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                final boolean sameAppId = appId == PrintManager.APP_ID_ANY
266269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        || printJob.getAppId() == appId;
267269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                final boolean sameState = (state == printJob.getState())
268269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        || (state == PrintJobInfo.STATE_ANY)
269269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        || (state == PrintJobInfo.STATE_ANY_VISIBLE_TO_CLIENTS
270d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov                            && isStateVisibleToUser(printJob.getState()))
271d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov                        || (state == PrintJobInfo.STATE_ANY_ACTIVE
2729b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov                            && isActiveState(printJob.getState()))
2739b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov                        || (state == PrintJobInfo.STATE_ANY_SCHEDULED
2749b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov                            && isScheduledState(printJob.getState()));
275269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                if (sameComponent && sameAppId && sameState) {
276269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    if (foundPrintJobs == null) {
277269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        foundPrintJobs = new ArrayList<PrintJobInfo>();
278269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    }
279269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    foundPrintJobs.add(printJob);
280269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                }
281269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
282269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
283269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        return foundPrintJobs;
284269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
285269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
286d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov    private boolean isStateVisibleToUser(int state) {
287d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov        return (isActiveState(state) && (state == PrintJobInfo.STATE_FAILED
2882fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                || state == PrintJobInfo.STATE_COMPLETED || state == PrintJobInfo.STATE_CANCELED
2892fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                || state == PrintJobInfo.STATE_BLOCKED));
290d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov    }
291d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov
2922fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    public PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId) {
293269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        synchronized (mLock) {
294269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            final int printJobCount = mPrintJobs.size();
295269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            for (int i = 0; i < printJobCount; i++) {
296269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                PrintJobInfo printJob = mPrintJobs.get(i);
2972fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                if (printJob.getId().equals(printJobId)
298269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        && (appId == PrintManager.APP_ID_ANY
299269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        || appId == printJob.getAppId())) {
300269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    return printJob;
301269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                }
302269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
303269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            return null;
304269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
305269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
306269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
3072fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    public void createPrintJob(PrintJobInfo printJob) {
308269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        synchronized (mLock) {
309269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            addPrintJobLocked(printJob);
310dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            setPrintJobState(printJob.getId(), PrintJobInfo.STATE_CREATED, null);
3117bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav
3127bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            Message message = mHandlerCaller.obtainMessageO(
3137bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                    HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED,
3147bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                    printJob);
3157bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            mHandlerCaller.executeOrSendMessage(message);
316269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
317269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
318269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
319269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    private void handleReadPrintJobsLocked() {
320dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov        // Make a map with the files for a print job since we may have
321dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov        // to delete some. One example of getting orphan files if the
322dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov        // spooler crashes while constructing a print job. We do not
323dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov        // persist partially populated print jobs under construction to
324dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov        // avoid special handling for various attributes missing.
325dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov        ArrayMap<PrintJobId, File> fileForJobMap = null;
326dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov        File[] files = getFilesDir().listFiles();
327dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov        if (files != null) {
328dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            final int fileCount = files.length;
329dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            for (int i = 0; i < fileCount; i++) {
330dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                File file = files[i];
331dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                if (file.isFile() && file.getName().startsWith(PRINT_JOB_FILE_PREFIX)) {
332dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                    if (fileForJobMap == null) {
333dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                        fileForJobMap = new ArrayMap<PrintJobId, File>();
334dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                    }
3352b40c83ae1ec17ea9371c3fd3ac6c79c156faa1dSvetoslav Ganov                    String printJobIdString = file.getName().substring(
3362b40c83ae1ec17ea9371c3fd3ac6c79c156faa1dSvetoslav Ganov                            PRINT_JOB_FILE_PREFIX.length(),
3372b40c83ae1ec17ea9371c3fd3ac6c79c156faa1dSvetoslav Ganov                            file.getName().indexOf('.'));
338dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                    PrintJobId printJobId = PrintJobId.unflattenFromString(
339dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                            printJobIdString);
340dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                    fileForJobMap.put(printJobId, file);
341dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                }
342dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            }
343dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov        }
344dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov
345269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        final int printJobCount = mPrintJobs.size();
346269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        for (int i = 0; i < printJobCount; i++) {
347269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            PrintJobInfo printJob = mPrintJobs.get(i);
348269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
349dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            // We want to have only the orphan files at the end.
350dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            if (fileForJobMap != null) {
351dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                fileForJobMap.remove(printJob.getId());
352dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            }
353dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov
354269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            switch (printJob.getState()) {
355269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                case PrintJobInfo.STATE_QUEUED:
356d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov                case PrintJobInfo.STATE_STARTED:
357d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov                case PrintJobInfo.STATE_BLOCKED: {
358d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov                    // We have a print job that was queued or started or blocked in
359d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov                    // the past but the device battery died or a crash occurred. In
360d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov                    // this case we assume the print job failed and let the user
361d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov                    // decide whether to restart the job or just cancel it.
362269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    setPrintJobState(printJob.getId(), PrintJobInfo.STATE_FAILED,
363269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            getString(R.string.no_connection_to_printer));
3642fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                } break;
365269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
366269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
367dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov
368a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        if (!mPrintJobs.isEmpty()) {
369a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            // Update the notification.
370a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            mNotificationController.onUpdateNotifications(mPrintJobs);
371a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        }
372a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov
373dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov        // Delete the orphan files.
374dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov        if (fileForJobMap != null) {
375dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            final int orphanFileCount = fileForJobMap.size();
376dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            for (int i = 0; i < orphanFileCount; i++) {
377dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                File file = fileForJobMap.valueAt(i);
378dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                file.delete();
379dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            }
380dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov        }
381269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
382269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
383269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    public void checkAllPrintJobsHandled() {
384269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        synchronized (mLock) {
385269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (!hasActivePrintJobsLocked()) {
386269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                notifyOnAllPrintJobsHandled();
387269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
388269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
389269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
390269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
3912fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    public void writePrintJobData(final ParcelFileDescriptor fd, final PrintJobId printJobId) {
392269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        final PrintJobInfo printJob;
393269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        synchronized (mLock) {
394269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
395269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
396269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        new AsyncTask<Void, Void, Void>() {
397269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            @Override
398269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            protected Void doInBackground(Void... params) {
399269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                FileInputStream in = null;
400269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                FileOutputStream out = null;
401269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                try {
402269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    if (printJob != null) {
403269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        File file = generateFileForPrintJob(printJobId);
404269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        in = new FileInputStream(file);
405269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        out = new FileOutputStream(fd.getFileDescriptor());
406269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    }
407269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    final byte[] buffer = new byte[8192];
408269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    while (true) {
409269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        final int readByteCount = in.read(buffer);
410269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        if (readByteCount < 0) {
411269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            return null;
412269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        }
413269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        out.write(buffer, 0, readByteCount);
414269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    }
415269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                } catch (FileNotFoundException fnfe) {
416269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    Log.e(LOG_TAG, "Error writing print job data!", fnfe);
417269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                } catch (IOException ioe) {
418269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    Log.e(LOG_TAG, "Error writing print job data!", ioe);
419269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                } finally {
420269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    IoUtils.closeQuietly(in);
421269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    IoUtils.closeQuietly(out);
422269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    IoUtils.closeQuietly(fd);
423269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                }
424269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                Log.i(LOG_TAG, "[END WRITE]");
425269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                return null;
426269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
427269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
428269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
429269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
4302fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    public File generateFileForPrintJob(PrintJobId printJobId) {
431dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov        return new File(getFilesDir(), PRINT_JOB_FILE_PREFIX
4322fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                + printJobId.flattenToString() + "." + PRINT_FILE_EXTENSION);
433269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
434269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
435269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    private void addPrintJobLocked(PrintJobInfo printJob) {
436269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        mPrintJobs.add(printJob);
437269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        if (DEBUG_PRINT_JOB_LIFECYCLE) {
438269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            Slog.i(LOG_TAG, "[ADD] " + printJob);
439269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
440269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
441269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
4422fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    private void removeObsoletePrintJobs() {
4432fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        synchronized (mLock) {
444885810de69d75979df4299d21fa236490767eae4Svetoslav            boolean persistState = false;
4452fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            final int printJobCount = mPrintJobs.size();
4462fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            for (int i = printJobCount - 1; i >= 0; i--) {
4472fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                PrintJobInfo printJob = mPrintJobs.get(i);
4482fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                if (isObsoleteState(printJob.getState())) {
4492fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                    mPrintJobs.remove(i);
4502fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                    if (DEBUG_PRINT_JOB_LIFECYCLE) {
4512fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                        Slog.i(LOG_TAG, "[REMOVE] " + printJob.getId().flattenToString());
4522fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                    }
4532fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                    removePrintJobFileLocked(printJob.getId());
454885810de69d75979df4299d21fa236490767eae4Svetoslav                    persistState = true;
4552fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                }
4562fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            }
457885810de69d75979df4299d21fa236490767eae4Svetoslav            if (persistState) {
458885810de69d75979df4299d21fa236490767eae4Svetoslav                mPersistanceManager.writeStateLocked();
459885810de69d75979df4299d21fa236490767eae4Svetoslav            }
4602fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        }
4612fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    }
4622fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav
4632fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    private void removePrintJobFileLocked(PrintJobId printJobId) {
4642fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        File file = generateFileForPrintJob(printJobId);
4652fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        if (file.exists()) {
4662fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            file.delete();
467269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (DEBUG_PRINT_JOB_LIFECYCLE) {
468dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                Slog.i(LOG_TAG, "[REMOVE FILE FOR] " + printJobId);
469269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
470269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
471269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
472269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
4732fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    public boolean setPrintJobState(PrintJobId printJobId, int state, String error) {
474269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        boolean success = false;
475269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
476269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        synchronized (mLock) {
477269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
478269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (printJob != null) {
479704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                final int oldState = printJob.getState();
480704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                if (oldState == state) {
481704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                    return false;
482704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                }
483704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov
484269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                success = true;
485269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
486269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                printJob.setState(state);
487d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov                printJob.setStateReason(error);
488a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                printJob.setCancelling(false);
489269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
490269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                if (DEBUG_PRINT_JOB_LIFECYCLE) {
491269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    Slog.i(LOG_TAG, "[STATE CHANGED] " + printJob);
492269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                }
493269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
494269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                switch (state) {
495269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    case PrintJobInfo.STATE_COMPLETED:
496269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    case PrintJobInfo.STATE_CANCELED:
497dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                        mPrintJobs.remove(printJob);
4982fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                        removePrintJobFileLocked(printJob.getId());
499269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        // $fall-through$
500269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
501269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    case PrintJobInfo.STATE_FAILED: {
502269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        PrinterId printerId = printJob.getPrinterId();
503269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        if (printerId != null) {
504269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            ComponentName service = printerId.getServiceName();
505269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            if (!hasActivePrintJobsForServiceLocked(service)) {
506269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                                sendOnAllPrintJobsForServiceHandled(service);
507269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            }
508269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        }
509269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    } break;
510269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
511269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    case PrintJobInfo.STATE_QUEUED: {
512269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        sendOnPrintJobQueued(new PrintJobInfo(printJob));
513269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    }  break;
514269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                }
515269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
516269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                if (shouldPersistPrintJob(printJob)) {
517269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    mPersistanceManager.writeStateLocked();
518269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                }
519269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
520269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                if (!hasActivePrintJobsLocked()) {
521269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    notifyOnAllPrintJobsHandled();
522269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                }
523704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov
524dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                Message message = mHandlerCaller.obtainMessageO(
525704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                        HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED,
526dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                        printJob);
527704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                mHandlerCaller.executeOrSendMessage(message);
528a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov
529a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                mNotificationController.onUpdateNotifications(mPrintJobs);
530269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
531269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
532269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
533269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        return success;
534269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
535269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
536269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    public boolean hasActivePrintJobsLocked() {
537269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        final int printJobCount = mPrintJobs.size();
538269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        for (int i = 0; i < printJobCount; i++) {
539269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            PrintJobInfo printJob = mPrintJobs.get(i);
540269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (isActiveState(printJob.getState())) {
541269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                return true;
542269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
543269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
544269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        return false;
545269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
546269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
547269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    public boolean hasActivePrintJobsForServiceLocked(ComponentName service) {
548269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        final int printJobCount = mPrintJobs.size();
549269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        for (int i = 0; i < printJobCount; i++) {
550269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            PrintJobInfo printJob = mPrintJobs.get(i);
55175d28505c8f73a977cc7ae0cc08a60120f7c92b2Svetoslav            if (isActiveState(printJob.getState()) && printJob.getPrinterId() != null
552269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    && printJob.getPrinterId().getServiceName().equals(service)) {
553269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                return true;
554269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
555269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
556269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        return false;
557269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
558269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
5592fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    private boolean isObsoleteState(int printJobState) {
5602fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        return (isTeminalState(printJobState)
5612fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                || printJobState == PrintJobInfo.STATE_QUEUED);
5622fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    }
5632fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav
5649b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov    private boolean isScheduledState(int printJobState) {
5659b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov        return printJobState == PrintJobInfo.STATE_QUEUED
5669b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov                || printJobState == PrintJobInfo.STATE_STARTED
5679b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov                || printJobState == PrintJobInfo.STATE_BLOCKED;
5689b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov    }
5699b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov
570269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    private boolean isActiveState(int printJobState) {
571269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        return printJobState == PrintJobInfo.STATE_CREATED
572269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                || printJobState == PrintJobInfo.STATE_QUEUED
573d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov                || printJobState == PrintJobInfo.STATE_STARTED
574d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov                || printJobState == PrintJobInfo.STATE_BLOCKED;
575269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
576269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
5772fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    private boolean isTeminalState(int printJobState) {
5782fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        return printJobState == PrintJobInfo.STATE_COMPLETED
5792fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                || printJobState == PrintJobInfo.STATE_CANCELED;
5802fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    }
5812fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav
5822fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    public boolean setPrintJobTag(PrintJobId printJobId, String tag) {
583269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        synchronized (mLock) {
584269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
585269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (printJob != null) {
586269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                String printJobTag = printJob.getTag();
587269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                if (printJobTag == null) {
588269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    if (tag == null) {
589269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        return false;
590269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    }
591269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                } else if (printJobTag.equals(tag)) {
592269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    return false;
593269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                }
594269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                printJob.setTag(tag);
595269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                if (shouldPersistPrintJob(printJob)) {
596269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    mPersistanceManager.writeStateLocked();
597269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                }
598269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                return true;
599269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
600269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
601269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        return false;
602269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
603269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
604a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov    public void setPrintJobCancelling(PrintJobId printJobId, boolean cancelling) {
605a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        synchronized (mLock) {
606a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
607a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            if (printJob != null) {
608a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                printJob.setCancelling(cancelling);
609a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                if (shouldPersistPrintJob(printJob)) {
610a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                    mPersistanceManager.writeStateLocked();
611a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                }
612a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                mNotificationController.onUpdateNotifications(mPrintJobs);
613a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov
614a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                Message message = mHandlerCaller.obtainMessageO(
615a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                        HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED,
616a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                        printJob);
617a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                mHandlerCaller.executeOrSendMessage(message);
618a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            }
619a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        }
620a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov    }
621a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov
6222fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    public void setPrintJobCopiesNoPersistence(PrintJobId printJobId, int copies) {
623269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        synchronized (mLock) {
624269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
625269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (printJob != null) {
626269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                printJob.setCopies(copies);
627269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
628269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
629269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
630269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
631b4fda134761c9521a7e127db3806a07a18763b77Svetoslav    public void setPrintJobAdvancedOptionsNoPersistence(PrintJobId printJobId,
632b4fda134761c9521a7e127db3806a07a18763b77Svetoslav            Bundle advancedOptions) {
633b4fda134761c9521a7e127db3806a07a18763b77Svetoslav        synchronized (mLock) {
634b4fda134761c9521a7e127db3806a07a18763b77Svetoslav            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
635b4fda134761c9521a7e127db3806a07a18763b77Svetoslav            if (printJob != null) {
636b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                printJob.setAdvancedOptions(advancedOptions);
637b4fda134761c9521a7e127db3806a07a18763b77Svetoslav            }
638b4fda134761c9521a7e127db3806a07a18763b77Svetoslav        }
639b4fda134761c9521a7e127db3806a07a18763b77Svetoslav    }
640b4fda134761c9521a7e127db3806a07a18763b77Svetoslav
6412fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    public void setPrintJobPrintDocumentInfoNoPersistence(PrintJobId printJobId,
6422fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            PrintDocumentInfo info) {
643269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        synchronized (mLock) {
644269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
645269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (printJob != null) {
646269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                printJob.setDocumentInfo(info);
647269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
648269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
649269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
650269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
6512fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    public void setPrintJobAttributesNoPersistence(PrintJobId printJobId,
6522fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            PrintAttributes attributes) {
653269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        synchronized (mLock) {
654269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
655269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (printJob != null) {
656269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                printJob.setAttributes(attributes);
657269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
658269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
659269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
660269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
6612fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    public void setPrintJobPrinterNoPersistence(PrintJobId printJobId, PrinterInfo printer) {
662269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        synchronized (mLock) {
663269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
664269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (printJob != null) {
665269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                printJob.setPrinterId(printer.getId());
666269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                printJob.setPrinterName(printer.getName());
667269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
668269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
669269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
670269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
6712fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    public void setPrintJobPagesNoPersistence(PrintJobId printJobId, PageRange[] pages) {
672269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        synchronized (mLock) {
673269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
674269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (printJob != null) {
675269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                printJob.setPages(pages);
676269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
677269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
678269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
679269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
680269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    private boolean shouldPersistPrintJob(PrintJobInfo printJob) {
681269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        return printJob.getState() >= PrintJobInfo.STATE_QUEUED;
682269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
683269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
684269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    private void notifyOnAllPrintJobsHandled() {
685269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        // This has to run on the tread that is persisting the current state
686269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        // since this call may result in the system unbinding from the spooler
687269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        // and as a result the spooler process may get killed before the write
688269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        // completes.
689269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        new AsyncTask<Void, Void, Void>() {
690269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            @Override
691269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            protected Void doInBackground(Void... params) {
692269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                sendOnAllPrintJobsHandled();
693269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                return null;
694269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
695269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
696269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
697269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
698269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    private final class PersistenceManager {
699269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String PERSIST_FILE_NAME = "print_spooler_state.xml";
700269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
701269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String TAG_SPOOLER = "spooler";
702269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String TAG_JOB = "job";
703269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
704269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String TAG_PRINTER_ID = "printerId";
705269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String TAG_PAGE_RANGE = "pageRange";
706269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String TAG_ATTRIBUTES = "attributes";
707269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String TAG_DOCUMENT_INFO = "documentInfo";
708269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
709269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String ATTR_ID = "id";
710269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String ATTR_LABEL = "label";
711773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav        private static final String ATTR_LABEL_RES_ID = "labelResId";
712773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav        private static final String ATTR_PACKAGE_NAME = "packageName";
713269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String ATTR_STATE = "state";
714269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String ATTR_APP_ID = "appId";
715269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String ATTR_TAG = "tag";
716704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        private static final String ATTR_CREATION_TIME = "creationTime";
717269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String ATTR_COPIES = "copies";
718704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        private static final String ATTR_PRINTER_NAME = "printerName";
719704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        private static final String ATTR_STATE_REASON = "stateReason";
720a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        private static final String ATTR_CANCELLING = "cancelling";
721269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
722b4fda134761c9521a7e127db3806a07a18763b77Svetoslav        private static final String TAG_ADVANCED_OPTIONS = "advancedOptions";
723b4fda134761c9521a7e127db3806a07a18763b77Svetoslav        private static final String TAG_ADVANCED_OPTION = "advancedOption";
724b4fda134761c9521a7e127db3806a07a18763b77Svetoslav        private static final String ATTR_KEY = "key";
725b4fda134761c9521a7e127db3806a07a18763b77Svetoslav        private static final String ATTR_TYPE = "type";
726b4fda134761c9521a7e127db3806a07a18763b77Svetoslav        private static final String ATTR_VALUE = "value";
727b4fda134761c9521a7e127db3806a07a18763b77Svetoslav        private static final String TYPE_STRING = "string";
728b4fda134761c9521a7e127db3806a07a18763b77Svetoslav        private static final String TYPE_INT = "int";
729b4fda134761c9521a7e127db3806a07a18763b77Svetoslav
730269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String TAG_MEDIA_SIZE = "mediaSize";
731269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String TAG_RESOLUTION = "resolution";
732269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String TAG_MARGINS = "margins";
733269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
734269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String ATTR_COLOR_MODE = "colorMode";
735269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
736704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        private static final String ATTR_LOCAL_ID = "localId";
737269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String ATTR_SERVICE_NAME = "serviceName";
738269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
739269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String ATTR_WIDTH_MILS = "widthMils";
740269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String ATTR_HEIGHT_MILS = "heightMils";
741269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
742269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String ATTR_HORIZONTAL_DPI = "horizontalDip";
743269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String ATTR_VERTICAL_DPI = "verticalDpi";
744269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
745269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String ATTR_LEFT_MILS = "leftMils";
746269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String ATTR_TOP_MILS = "topMils";
747269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String ATTR_RIGHT_MILS = "rightMils";
748269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String ATTR_BOTTOM_MILS = "bottomMils";
749269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
750269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String ATTR_START = "start";
751269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String ATTR_END = "end";
752269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
753269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String ATTR_NAME = "name";
754269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String ATTR_PAGE_COUNT = "pageCount";
755269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private static final String ATTR_CONTENT_TYPE = "contentType";
7567d7888d1c7daa78ee0ad24a24c8dd54b01749259Svetoslav Ganov        private static final String ATTR_DATA_SIZE = "dataSize";
757269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
758269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private final AtomicFile mStatePersistFile;
759269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
760269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private boolean mWriteStateScheduled;
761269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
762269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private PersistenceManager() {
763269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            mStatePersistFile = new AtomicFile(new File(getFilesDir(),
764269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    PERSIST_FILE_NAME));
765269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
766269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
767269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        public void writeStateLocked() {
768269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (!PERSISTNECE_MANAGER_ENABLED) {
769269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                return;
770269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
771269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (mWriteStateScheduled) {
772269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                return;
773269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
774269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            mWriteStateScheduled = true;
775269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            new AsyncTask<Void, Void, Void>() {
776269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                @Override
777269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                protected Void doInBackground(Void... params) {
778269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    synchronized (mLock) {
779269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        mWriteStateScheduled = false;
780269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        doWriteStateLocked();
781269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    }
782269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    return null;
783269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                }
784269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
785269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
786269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
787269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private void doWriteStateLocked() {
788269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (DEBUG_PERSISTENCE) {
789269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                Log.i(LOG_TAG, "[PERSIST START]");
790269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
791269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            FileOutputStream out = null;
792269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            try {
793269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                out = mStatePersistFile.startWrite();
794269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
795269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                XmlSerializer serializer = new FastXmlSerializer();
796269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                serializer.setOutput(out, "utf-8");
797269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                serializer.startDocument(null, true);
798269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                serializer.startTag(null, TAG_SPOOLER);
799269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
800269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                List<PrintJobInfo> printJobs = mPrintJobs;
801269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
802269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                final int printJobCount = printJobs.size();
803269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                for (int j = 0; j < printJobCount; j++) {
804269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    PrintJobInfo printJob = printJobs.get(j);
805269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
806885810de69d75979df4299d21fa236490767eae4Svetoslav                    if (!shouldPersistPrintJob(printJob)) {
807885810de69d75979df4299d21fa236490767eae4Svetoslav                        continue;
808885810de69d75979df4299d21fa236490767eae4Svetoslav                    }
809885810de69d75979df4299d21fa236490767eae4Svetoslav
810269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    serializer.startTag(null, TAG_JOB);
811269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
8122fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                    serializer.attribute(null, ATTR_ID, printJob.getId().flattenToString());
813269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    serializer.attribute(null, ATTR_LABEL, printJob.getLabel().toString());
814269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    serializer.attribute(null, ATTR_STATE, String.valueOf(printJob.getState()));
815269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    serializer.attribute(null, ATTR_APP_ID, String.valueOf(printJob.getAppId()));
816269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    String tag = printJob.getTag();
817269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    if (tag != null) {
818269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        serializer.attribute(null, ATTR_TAG, tag);
819269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    }
820704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                    serializer.attribute(null, ATTR_CREATION_TIME, String.valueOf(
821704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                            printJob.getCreationTime()));
822269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    serializer.attribute(null, ATTR_COPIES, String.valueOf(printJob.getCopies()));
823704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                    String printerName = printJob.getPrinterName();
824704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                    if (!TextUtils.isEmpty(printerName)) {
825704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                        serializer.attribute(null, ATTR_PRINTER_NAME, printerName);
826704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                    }
827704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                    String stateReason = printJob.getStateReason();
828704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                    if (!TextUtils.isEmpty(stateReason)) {
829704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                        serializer.attribute(null, ATTR_STATE_REASON, stateReason);
830704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                    }
831a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                    serializer.attribute(null, ATTR_CANCELLING, String.valueOf(
832a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                            printJob.isCancelling()));
833269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
834269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    PrinterId printerId = printJob.getPrinterId();
835269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    if (printerId != null) {
836269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        serializer.startTag(null, TAG_PRINTER_ID);
837269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        serializer.attribute(null, ATTR_LOCAL_ID, printerId.getLocalId());
838269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        serializer.attribute(null, ATTR_SERVICE_NAME, printerId.getServiceName()
839269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                                .flattenToString());
840269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        serializer.endTag(null, TAG_PRINTER_ID);
841269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    }
842269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
843269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    PageRange[] pages = printJob.getPages();
844269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    if (pages != null) {
845269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        for (int i = 0; i < pages.length; i++) {
846269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            serializer.startTag(null, TAG_PAGE_RANGE);
847269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            serializer.attribute(null, ATTR_START, String.valueOf(
848269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                                    pages[i].getStart()));
849269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            serializer.attribute(null, ATTR_END, String.valueOf(
850269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                                    pages[i].getEnd()));
851269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            serializer.endTag(null, TAG_PAGE_RANGE);
852269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        }
853269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    }
854269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
855269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    PrintAttributes attributes = printJob.getAttributes();
856269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    if (attributes != null) {
857269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        serializer.startTag(null, TAG_ATTRIBUTES);
858269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
859269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        final int colorMode = attributes.getColorMode();
860269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        serializer.attribute(null, ATTR_COLOR_MODE,
861269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                                String.valueOf(colorMode));
862269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
863269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        MediaSize mediaSize = attributes.getMediaSize();
864269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        if (mediaSize != null) {
865269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            serializer.startTag(null, TAG_MEDIA_SIZE);
866269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            serializer.attribute(null, ATTR_ID, mediaSize.getId());
867269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            serializer.attribute(null, ATTR_WIDTH_MILS, String.valueOf(
868269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                                    mediaSize.getWidthMils()));
869269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            serializer.attribute(null, ATTR_HEIGHT_MILS, String.valueOf(
870269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                                    mediaSize.getHeightMils()));
871a76233ae845da4bc9e3bcd89821701a747215e7bSvetoslav                            // We prefer to store only the package name and
872a76233ae845da4bc9e3bcd89821701a747215e7bSvetoslav                            // resource id and fallback to the label.
873a76233ae845da4bc9e3bcd89821701a747215e7bSvetoslav                            if (!TextUtils.isEmpty(mediaSize.mPackageName)
874773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav                                    && mediaSize.mLabelResId > 0) {
875773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav                                serializer.attribute(null, ATTR_PACKAGE_NAME,
876773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav                                        mediaSize.mPackageName);
877773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav                                serializer.attribute(null, ATTR_LABEL_RES_ID,
878773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav                                        String.valueOf(mediaSize.mLabelResId));
879773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav                            } else {
880773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav                                serializer.attribute(null, ATTR_LABEL,
881773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav                                        mediaSize.getLabel(getPackageManager()));
882773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav                            }
883269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            serializer.endTag(null, TAG_MEDIA_SIZE);
884269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        }
885269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
886269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        Resolution resolution = attributes.getResolution();
887269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        if (resolution != null) {
888269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            serializer.startTag(null, TAG_RESOLUTION);
889269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            serializer.attribute(null, ATTR_ID, resolution.getId());
890269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            serializer.attribute(null, ATTR_HORIZONTAL_DPI, String.valueOf(
891269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                                    resolution.getHorizontalDpi()));
892269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            serializer.attribute(null, ATTR_VERTICAL_DPI, String.valueOf(
893269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                                    resolution.getVerticalDpi()));
894c6066799ad130140159230d14451b429eb828755Svetoslav                            serializer.attribute(null, ATTR_LABEL,
895651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav                                    resolution.getLabel());
896269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            serializer.endTag(null, TAG_RESOLUTION);
897269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        }
898269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
899651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav                        Margins margins = attributes.getMinMargins();
900269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        if (margins != null) {
901269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            serializer.startTag(null, TAG_MARGINS);
902269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            serializer.attribute(null, ATTR_LEFT_MILS, String.valueOf(
903269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                                    margins.getLeftMils()));
904269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            serializer.attribute(null, ATTR_TOP_MILS, String.valueOf(
905269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                                    margins.getTopMils()));
906269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            serializer.attribute(null, ATTR_RIGHT_MILS, String.valueOf(
907269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                                    margins.getRightMils()));
908269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            serializer.attribute(null, ATTR_BOTTOM_MILS, String.valueOf(
909269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                                    margins.getBottomMils()));
910269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            serializer.endTag(null, TAG_MARGINS);
911269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        }
912269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
913269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        serializer.endTag(null, TAG_ATTRIBUTES);
914269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    }
915269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
916269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    PrintDocumentInfo documentInfo = printJob.getDocumentInfo();
917269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    if (documentInfo != null) {
918269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        serializer.startTag(null, TAG_DOCUMENT_INFO);
919269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        serializer.attribute(null, ATTR_NAME, documentInfo.getName());
920269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        serializer.attribute(null, ATTR_CONTENT_TYPE, String.valueOf(
921269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                                documentInfo.getContentType()));
922269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        serializer.attribute(null, ATTR_PAGE_COUNT, String.valueOf(
923269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                                documentInfo.getPageCount()));
9247d7888d1c7daa78ee0ad24a24c8dd54b01749259Svetoslav Ganov                        serializer.attribute(null, ATTR_DATA_SIZE, String.valueOf(
9257d7888d1c7daa78ee0ad24a24c8dd54b01749259Svetoslav Ganov                                documentInfo.getDataSize()));
926269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        serializer.endTag(null, TAG_DOCUMENT_INFO);
927269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    }
928269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
929b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                    Bundle advancedOptions = printJob.getAdvancedOptions();
930b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                    if (advancedOptions != null) {
931b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                        serializer.startTag(null, TAG_ADVANCED_OPTIONS);
932b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                        for (String key : advancedOptions.keySet()) {
933b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                            Object value = advancedOptions.get(key);
934b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                            if (value instanceof String) {
935b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                                String stringValue = (String) value;
936b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                                serializer.startTag(null, TAG_ADVANCED_OPTION);
937b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                                serializer.attribute(null, ATTR_KEY, key);
938b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                                serializer.attribute(null, ATTR_TYPE, TYPE_STRING);
939b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                                serializer.attribute(null, ATTR_VALUE, stringValue);
940b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                                serializer.endTag(null, TAG_ADVANCED_OPTION);
941b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                            } else if (value instanceof Integer) {
942b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                                String intValue = Integer.toString((Integer) value);
943b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                                serializer.startTag(null, TAG_ADVANCED_OPTION);
944b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                                serializer.attribute(null, ATTR_KEY, key);
945b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                                serializer.attribute(null, ATTR_TYPE, TYPE_INT);
946b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                                serializer.attribute(null, ATTR_VALUE, intValue);
947b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                                serializer.endTag(null, TAG_ADVANCED_OPTION);
948b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                            }
949b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                        }
950b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                        serializer.endTag(null, TAG_ADVANCED_OPTIONS);
951b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                    }
952b4fda134761c9521a7e127db3806a07a18763b77Svetoslav
953269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    serializer.endTag(null, TAG_JOB);
954269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
955269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    if (DEBUG_PERSISTENCE) {
956269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        Log.i(LOG_TAG, "[PERSISTED] " + printJob);
957269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    }
958269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                }
959269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
960269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                serializer.endTag(null, TAG_SPOOLER);
961269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                serializer.endDocument();
962269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                mStatePersistFile.finishWrite(out);
963269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                if (DEBUG_PERSISTENCE) {
964269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    Log.i(LOG_TAG, "[PERSIST END]");
965269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                }
966269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            } catch (IOException e) {
967269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                Slog.w(LOG_TAG, "Failed to write state, restoring backup.", e);
968269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                mStatePersistFile.failWrite(out);
969269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            } finally {
970269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                IoUtils.closeQuietly(out);
971269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
972269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
973269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
974269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        public void readStateLocked() {
975269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (!PERSISTNECE_MANAGER_ENABLED) {
976269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                return;
977269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
978269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            FileInputStream in = null;
979269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            try {
980269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                in = mStatePersistFile.openRead();
981269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            } catch (FileNotFoundException e) {
982269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                Log.i(LOG_TAG, "No existing print spooler state.");
983269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                return;
984269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
985269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            try {
986269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                XmlPullParser parser = Xml.newPullParser();
987269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                parser.setInput(in, null);
988269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                parseState(parser);
989269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            } catch (IllegalStateException ise) {
990269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                Slog.w(LOG_TAG, "Failed parsing ", ise);
991269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            } catch (NullPointerException npe) {
992269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                Slog.w(LOG_TAG, "Failed parsing ", npe);
993269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            } catch (NumberFormatException nfe) {
994269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                Slog.w(LOG_TAG, "Failed parsing ", nfe);
995269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            } catch (XmlPullParserException xppe) {
996269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                Slog.w(LOG_TAG, "Failed parsing ", xppe);
997269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            } catch (IOException ioe) {
998269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                Slog.w(LOG_TAG, "Failed parsing ", ioe);
999269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            } catch (IndexOutOfBoundsException iobe) {
1000269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                Slog.w(LOG_TAG, "Failed parsing ", iobe);
1001269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            } finally {
1002269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                IoUtils.closeQuietly(in);
1003269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
1004269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
1005269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1006269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private void parseState(XmlPullParser parser)
1007269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                throws IOException, XmlPullParserException {
1008269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            parser.next();
1009269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            skipEmptyTextTags(parser);
1010269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            expect(parser, XmlPullParser.START_TAG, TAG_SPOOLER);
1011269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            parser.next();
1012269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1013269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            while (parsePrintJob(parser)) {
1014269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                parser.next();
1015269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
1016269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1017269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            skipEmptyTextTags(parser);
1018269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            expect(parser, XmlPullParser.END_TAG, TAG_SPOOLER);
1019269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
1020269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1021269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private boolean parsePrintJob(XmlPullParser parser)
1022269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                throws IOException, XmlPullParserException {
1023269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            skipEmptyTextTags(parser);
1024269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (!accept(parser, XmlPullParser.START_TAG, TAG_JOB)) {
1025269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                return false;
1026269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
1027269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1028269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            PrintJobInfo printJob = new PrintJobInfo();
1029269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
10302fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            PrintJobId printJobId = PrintJobId.unflattenFromString(
10312fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                    parser.getAttributeValue(null, ATTR_ID));
1032269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            printJob.setId(printJobId);
1033269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            String label = parser.getAttributeValue(null, ATTR_LABEL);
1034269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            printJob.setLabel(label);
1035269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            final int state = Integer.parseInt(parser.getAttributeValue(null, ATTR_STATE));
1036269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            printJob.setState(state);
1037269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            final int appId = Integer.parseInt(parser.getAttributeValue(null, ATTR_APP_ID));
1038269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            printJob.setAppId(appId);
1039269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            String tag = parser.getAttributeValue(null, ATTR_TAG);
1040269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            printJob.setTag(tag);
1041704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            String creationTime = parser.getAttributeValue(null, ATTR_CREATION_TIME);
1042704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            printJob.setCreationTime(Long.parseLong(creationTime));
1043269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            String copies = parser.getAttributeValue(null, ATTR_COPIES);
1044269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            printJob.setCopies(Integer.parseInt(copies));
1045704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            String printerName = parser.getAttributeValue(null, ATTR_PRINTER_NAME);
1046704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            printJob.setPrinterName(printerName);
1047704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            String stateReason = parser.getAttributeValue(null, ATTR_STATE_REASON);
1048704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            printJob.setStateReason(stateReason);
1049a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            String cancelling = parser.getAttributeValue(null, ATTR_CANCELLING);
1050a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            printJob.setCancelling(!TextUtils.isEmpty(cancelling)
1051a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                    ? Boolean.parseBoolean(cancelling) : false);
1052269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1053269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            parser.next();
1054269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1055269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            skipEmptyTextTags(parser);
1056269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (accept(parser, XmlPullParser.START_TAG, TAG_PRINTER_ID)) {
1057269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                String localId = parser.getAttributeValue(null, ATTR_LOCAL_ID);
1058269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                ComponentName service = ComponentName.unflattenFromString(parser.getAttributeValue(
1059269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        null, ATTR_SERVICE_NAME));
1060269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                printJob.setPrinterId(new PrinterId(service, localId));
1061269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                parser.next();
1062269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                skipEmptyTextTags(parser);
1063269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                expect(parser, XmlPullParser.END_TAG, TAG_PRINTER_ID);
1064269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                parser.next();
1065269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
1066269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1067269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            skipEmptyTextTags(parser);
1068269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            List<PageRange> pageRanges = null;
1069269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            while (accept(parser, XmlPullParser.START_TAG, TAG_PAGE_RANGE)) {
1070269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                final int start = Integer.parseInt(parser.getAttributeValue(null, ATTR_START));
1071269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                final int end = Integer.parseInt(parser.getAttributeValue(null, ATTR_END));
1072269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                PageRange pageRange = new PageRange(start, end);
1073269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                if (pageRanges == null) {
1074269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    pageRanges = new ArrayList<PageRange>();
1075269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                }
1076269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                pageRanges.add(pageRange);
1077269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                parser.next();
1078269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                skipEmptyTextTags(parser);
1079269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                expect(parser, XmlPullParser.END_TAG, TAG_PAGE_RANGE);
1080269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                parser.next();
1081b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                skipEmptyTextTags(parser);
1082269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
1083269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (pageRanges != null) {
1084269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                PageRange[] pageRangesArray = new PageRange[pageRanges.size()];
1085269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                pageRanges.toArray(pageRangesArray);
1086269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                printJob.setPages(pageRangesArray);
1087269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
1088269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1089269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            skipEmptyTextTags(parser);
1090269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (accept(parser, XmlPullParser.START_TAG, TAG_ATTRIBUTES)) {
1091269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1092269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                PrintAttributes.Builder builder = new PrintAttributes.Builder();
1093269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1094269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                String colorMode = parser.getAttributeValue(null, ATTR_COLOR_MODE);
1095269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                builder.setColorMode(Integer.parseInt(colorMode));
1096269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1097269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                parser.next();
1098269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1099269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                skipEmptyTextTags(parser);
1100269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                if (accept(parser, XmlPullParser.START_TAG, TAG_MEDIA_SIZE)) {
1101269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    String id = parser.getAttributeValue(null, ATTR_ID);
1102269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    label = parser.getAttributeValue(null, ATTR_LABEL);
1103269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    final int widthMils = Integer.parseInt(parser.getAttributeValue(null,
1104269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            ATTR_WIDTH_MILS));
1105269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    final int heightMils = Integer.parseInt(parser.getAttributeValue(null,
1106269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            ATTR_HEIGHT_MILS));
1107773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav                    String packageName = parser.getAttributeValue(null, ATTR_PACKAGE_NAME);
1108b206f1271d17164c3f2f65219eee7a0b4b4fa6dcSvetoslav                    String labelResIdString = parser.getAttributeValue(null, ATTR_LABEL_RES_ID);
1109b206f1271d17164c3f2f65219eee7a0b4b4fa6dcSvetoslav                    final int labelResId = (labelResIdString != null)
1110b206f1271d17164c3f2f65219eee7a0b4b4fa6dcSvetoslav                            ? Integer.parseInt(labelResIdString) : 0;
1111773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav                    label = parser.getAttributeValue(null, ATTR_LABEL);
1112b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                    MediaSize mediaSize = new MediaSize(id, label, packageName,
1113b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                                widthMils, heightMils, labelResId);
1114269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    builder.setMediaSize(mediaSize);
1115269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    parser.next();
1116269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    skipEmptyTextTags(parser);
1117269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    expect(parser, XmlPullParser.END_TAG, TAG_MEDIA_SIZE);
1118269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    parser.next();
1119269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                }
1120269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1121269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                skipEmptyTextTags(parser);
1122269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                if (accept(parser, XmlPullParser.START_TAG, TAG_RESOLUTION)) {
1123269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    String id = parser.getAttributeValue(null, ATTR_ID);
1124269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    label = parser.getAttributeValue(null, ATTR_LABEL);
1125269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    final int horizontalDpi = Integer.parseInt(parser.getAttributeValue(null,
1126269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            ATTR_HORIZONTAL_DPI));
1127269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    final int verticalDpi = Integer.parseInt(parser.getAttributeValue(null,
1128269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            ATTR_VERTICAL_DPI));
1129c6066799ad130140159230d14451b429eb828755Svetoslav                    Resolution resolution = new Resolution(id, label, horizontalDpi, verticalDpi);
1130269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    builder.setResolution(resolution);
1131269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    parser.next();
1132269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    skipEmptyTextTags(parser);
1133269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    expect(parser, XmlPullParser.END_TAG, TAG_RESOLUTION);
1134269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    parser.next();
1135269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                }
1136269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1137269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                skipEmptyTextTags(parser);
1138269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                if (accept(parser, XmlPullParser.START_TAG, TAG_MARGINS)) {
1139269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    final int leftMils = Integer.parseInt(parser.getAttributeValue(null,
1140269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            ATTR_LEFT_MILS));
1141269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    final int topMils = Integer.parseInt(parser.getAttributeValue(null,
1142269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            ATTR_TOP_MILS));
1143269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    final int rightMils = Integer.parseInt(parser.getAttributeValue(null,
1144269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            ATTR_RIGHT_MILS));
1145269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    final int bottomMils = Integer.parseInt(parser.getAttributeValue(null,
1146269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                            ATTR_BOTTOM_MILS));
1147269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    Margins margins = new Margins(leftMils, topMils, rightMils, bottomMils);
1148651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav                    builder.setMinMargins(margins);
1149269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    parser.next();
1150269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    skipEmptyTextTags(parser);
1151269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    expect(parser, XmlPullParser.END_TAG, TAG_MARGINS);
1152269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    parser.next();
1153269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                }
1154269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1155651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav                printJob.setAttributes(builder.build());
1156269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1157269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                skipEmptyTextTags(parser);
1158269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                expect(parser, XmlPullParser.END_TAG, TAG_ATTRIBUTES);
1159269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                parser.next();
1160269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
1161269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1162269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            skipEmptyTextTags(parser);
1163269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (accept(parser, XmlPullParser.START_TAG, TAG_DOCUMENT_INFO)) {
1164269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                String name = parser.getAttributeValue(null, ATTR_NAME);
1165269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                final int pageCount = Integer.parseInt(parser.getAttributeValue(null,
1166269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        ATTR_PAGE_COUNT));
1167269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                final int contentType = Integer.parseInt(parser.getAttributeValue(null,
1168269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        ATTR_CONTENT_TYPE));
11697d7888d1c7daa78ee0ad24a24c8dd54b01749259Svetoslav Ganov                final int dataSize = Integer.parseInt(parser.getAttributeValue(null,
11707d7888d1c7daa78ee0ad24a24c8dd54b01749259Svetoslav Ganov                        ATTR_DATA_SIZE));
1171269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                PrintDocumentInfo info = new PrintDocumentInfo.Builder(name)
1172269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        .setPageCount(pageCount)
1173651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav                        .setContentType(contentType).build();
1174269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                printJob.setDocumentInfo(info);
11757d7888d1c7daa78ee0ad24a24c8dd54b01749259Svetoslav Ganov                info.setDataSize(dataSize);
1176269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                parser.next();
1177269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                skipEmptyTextTags(parser);
1178269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                expect(parser, XmlPullParser.END_TAG, TAG_DOCUMENT_INFO);
1179269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                parser.next();
1180269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
1181269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1182b4fda134761c9521a7e127db3806a07a18763b77Svetoslav            skipEmptyTextTags(parser);
1183b4fda134761c9521a7e127db3806a07a18763b77Svetoslav            if (accept(parser, XmlPullParser.START_TAG, TAG_ADVANCED_OPTIONS)) {
1184b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                parser.next();
1185b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                skipEmptyTextTags(parser);
1186b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                Bundle advancedOptions = new Bundle();
1187b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                while (accept(parser, XmlPullParser.START_TAG, TAG_ADVANCED_OPTION)) {
1188b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                    String key = parser.getAttributeValue(null, ATTR_KEY);
1189b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                    String value = parser.getAttributeValue(null, ATTR_VALUE);
1190b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                    String type = parser.getAttributeValue(null, ATTR_TYPE);
1191b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                    if (TYPE_STRING.equals(type)) {
1192b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                        advancedOptions.putString(key, value);
1193b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                    } else if (TYPE_INT.equals(type)) {
1194b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                        advancedOptions.putInt(key, Integer.valueOf(value));
1195b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                    }
1196b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                    parser.next();
1197b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                    skipEmptyTextTags(parser);
1198b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                    expect(parser, XmlPullParser.END_TAG, TAG_ADVANCED_OPTION);
1199b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                    parser.next();
1200b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                    skipEmptyTextTags(parser);
1201b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                }
1202b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                printJob.setAdvancedOptions(advancedOptions);
1203b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                skipEmptyTextTags(parser);
1204b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                expect(parser, XmlPullParser.END_TAG, TAG_ADVANCED_OPTIONS);
1205b4fda134761c9521a7e127db3806a07a18763b77Svetoslav                parser.next();
1206b4fda134761c9521a7e127db3806a07a18763b77Svetoslav            }
1207b4fda134761c9521a7e127db3806a07a18763b77Svetoslav
1208269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            mPrintJobs.add(printJob);
1209269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1210269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (DEBUG_PERSISTENCE) {
1211269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                Log.i(LOG_TAG, "[RESTORED] " + printJob);
1212269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
1213269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1214269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            skipEmptyTextTags(parser);
1215269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            expect(parser, XmlPullParser.END_TAG, TAG_JOB);
1216269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1217269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            return true;
1218269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
1219269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1220269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private void expect(XmlPullParser parser, int type, String tag)
1221269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                throws IOException, XmlPullParserException {
1222269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (!accept(parser, type, tag)) {
1223269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                throw new XmlPullParserException("Exepected event: " + type
1224269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        + " and tag: " + tag + " but got event: " + parser.getEventType()
1225269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                        + " and tag:" + parser.getName());
1226269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
1227269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
1228269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1229269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private void skipEmptyTextTags(XmlPullParser parser)
1230269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                throws IOException, XmlPullParserException {
1231269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            while (accept(parser, XmlPullParser.TEXT, null)
1232269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    && "\n".equals(parser.getText())) {
1233269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                parser.next();
1234269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
1235269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
1236269403b032f965ff3847eb982c2f697229dc5a92Svetoslav
1237269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        private boolean accept(XmlPullParser parser, int type, String tag)
1238269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                throws IOException, XmlPullParserException {
1239269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (parser.getEventType() != type) {
1240269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                return false;
1241269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
1242269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            if (tag != null) {
1243269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                if (!tag.equals(parser.getName())) {
1244269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    return false;
1245269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                }
1246269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            } else if (parser.getName() != null) {
1247269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                return false;
1248269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            }
1249269403b032f965ff3847eb982c2f697229dc5a92Svetoslav            return true;
1250269403b032f965ff3847eb982c2f697229dc5a92Svetoslav        }
1251269403b032f965ff3847eb982c2f697229dc5a92Svetoslav    }
12527bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav
12537bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav    final class PrintSpooler extends IPrintSpooler.Stub {
12547bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        @Override
12557bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        public void getPrintJobInfos(IPrintSpoolerCallbacks callback,
12567bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                ComponentName componentName, int state, int appId, int sequence)
12577bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                throws RemoteException {
12587bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            List<PrintJobInfo> printJobs = null;
12597bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            try {
12607bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                printJobs = PrintSpoolerService.this.getPrintJobInfos(
12617bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                        componentName, state, appId);
12627bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            } finally {
12637bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                callback.onGetPrintJobInfosResult(printJobs, sequence);
12647bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            }
12657bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        }
12667bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav
12677bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        @Override
12687bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        public void getPrintJobInfo(PrintJobId printJobId, IPrintSpoolerCallbacks callback,
12697bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                int appId, int sequence) throws RemoteException {
12707bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            PrintJobInfo printJob = null;
12717bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            try {
12727bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                printJob = PrintSpoolerService.this.getPrintJobInfo(printJobId, appId);
12737bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            } finally {
12747bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                callback.onGetPrintJobInfoResult(printJob, sequence);
12757bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            }
12767bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        }
12777bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav
12787bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        @Override
12797bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        public void createPrintJob(PrintJobInfo printJob) {
12807bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            PrintSpoolerService.this.createPrintJob(printJob);
12817bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        }
12827bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav
12837bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        @Override
12847bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        public void setPrintJobState(PrintJobId printJobId, int state, String error,
12857bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                IPrintSpoolerCallbacks callback, int sequece) throws RemoteException {
12867bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            boolean success = false;
12877bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            try {
12887bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                success = PrintSpoolerService.this.setPrintJobState(
12897bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                        printJobId, state, error);
12907bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            } finally {
12917bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                callback.onSetPrintJobStateResult(success, sequece);
12927bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            }
12937bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        }
12947bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav
12957bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        @Override
12967bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        public void setPrintJobTag(PrintJobId printJobId, String tag,
12977bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                IPrintSpoolerCallbacks callback, int sequece) throws RemoteException {
12987bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            boolean success = false;
12997bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            try {
13007bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                success = PrintSpoolerService.this.setPrintJobTag(printJobId, tag);
13017bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            } finally {
13027bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                callback.onSetPrintJobTagResult(success, sequece);
13037bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            }
13047bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        }
13057bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav
13067bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        @Override
13077bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        public void writePrintJobData(ParcelFileDescriptor fd, PrintJobId printJobId) {
13087bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            PrintSpoolerService.this.writePrintJobData(fd, printJobId);
13097bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        }
13107bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav
13117bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        @Override
13127bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        public void setClient(IPrintSpoolerClient client) {
13137bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            Message message = mHandlerCaller.obtainMessageO(
13147bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                    HandlerCallerCallback.MSG_SET_CLIENT, client);
13157bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            mHandlerCaller.executeOrSendMessage(message);
13167bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        }
13177bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav
13187bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        @Override
13197bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        public void removeObsoletePrintJobs() {
13207bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            PrintSpoolerService.this.removeObsoletePrintJobs();
13217bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        }
13227bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav
13237bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        @Override
13247bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
13257bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            PrintSpoolerService.this.dump(fd, writer, args);
13267bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        }
13277bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav
13287bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        @Override
13297bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        public void setPrintJobCancelling(PrintJobId printJobId, boolean cancelling) {
13307bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            PrintSpoolerService.this.setPrintJobCancelling(printJobId, cancelling);
13317bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        }
13327bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav
13337bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        public PrintSpoolerService getService() {
13347bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            return PrintSpoolerService.this;
13357bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav        }
13367bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav    }
13374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov}
1338