PrintSpoolerService.java revision 9b6d3a153f44010a75907c6a9742c89a57d4e5ee
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; 234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.IBinder; 244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Message; 254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.ParcelFileDescriptor; 264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.RemoteException; 27a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.IPrintSpooler; 28a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.IPrintSpoolerCallbacks; 29835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganovimport android.print.IPrintSpoolerClient; 30269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PageRange; 314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.PrintAttributes; 32269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrintAttributes.Margins; 33269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrintAttributes.MediaSize; 34269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrintAttributes.Resolution; 35269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrintDocumentInfo; 362fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslavimport android.print.PrintJobId; 374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.PrintJobInfo; 38269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrintManager; 39269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrinterId; 40269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrinterInfo; 41a76233ae845da4bc9e3bcd89821701a747215e7bSvetoslavimport android.text.TextUtils; 42dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganovimport android.util.ArrayMap; 43269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.util.AtomicFile; 44835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganovimport android.util.Log; 454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.util.Slog; 46269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.util.Xml; 474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 48269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport com.android.internal.os.HandlerCaller; 49269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport com.android.internal.util.FastXmlSerializer; 504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 512fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslavimport libcore.io.IoUtils; 522fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav 53269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport org.xmlpull.v1.XmlPullParser; 54269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport org.xmlpull.v1.XmlPullParserException; 55269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport org.xmlpull.v1.XmlSerializer; 56269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 57269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.io.File; 58dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganovimport java.io.FileDescriptor; 59269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.io.FileInputStream; 60269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.io.FileNotFoundException; 61269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.io.FileOutputStream; 62269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.io.IOException; 63dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganovimport java.io.PrintWriter; 64269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.util.ArrayList; 65835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganovimport java.util.List; 66835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov 674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/** 684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Service for exposing some of the {@link PrintSpooler} functionality to 694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * another process. 704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovpublic final class PrintSpoolerService extends Service { 724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 73269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String LOG_TAG = "PrintSpoolerService"; 74269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 75b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav private static final boolean DEBUG_PRINT_JOB_LIFECYCLE = false; 76269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 77c6066799ad130140159230d14451b429eb828755Svetoslav private static final boolean DEBUG_PERSISTENCE = false; 78269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 79269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final boolean PERSISTNECE_MANAGER_ENABLED = true; 80269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 81835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov private static final long CHECK_ALL_PRINTJOBS_HANDLED_DELAY = 5000; 82835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov 83dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov private static final String PRINT_JOB_FILE_PREFIX = "print_job_"; 84dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 85269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String PRINT_FILE_EXTENSION = "pdf"; 86269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 87269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final Object sLock = new Object(); 88269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 89269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private final Object mLock = new Object(); 90269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 91269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private final List<PrintJobInfo> mPrintJobs = new ArrayList<PrintJobInfo>(); 92269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 93269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static PrintSpoolerService sInstance; 94269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 95835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov private IPrintSpoolerClient mClient; 964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 97269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private HandlerCaller mHandlerCaller; 98269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 99269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private PersistenceManager mPersistanceManager; 100269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 101269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private NotificationController mNotificationController; 102269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 103269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public static PrintSpoolerService peekInstance() { 104269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (sLock) { 105269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return sInstance; 106269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 107269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 1104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void onCreate() { 1114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov super.onCreate(); 112269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mHandlerCaller = new HandlerCaller(this, getMainLooper(), 113269403b032f965ff3847eb982c2f697229dc5a92Svetoslav new HandlerCallerCallback(), false); 114269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 115269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mPersistanceManager = new PersistenceManager(); 116269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mNotificationController = new NotificationController(PrintSpoolerService.this); 117269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 118269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 119269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mPersistanceManager.readStateLocked(); 120269403b032f965ff3847eb982c2f697229dc5a92Svetoslav handleReadPrintJobsLocked(); 121269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 122269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 123269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (sLock) { 124269403b032f965ff3847eb982c2f697229dc5a92Svetoslav sInstance = this; 125269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 1294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public IBinder onBind(Intent intent) { 1307bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav return new PrintSpooler(); 1314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 133dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov @Override 134dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 135dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov synchronized (mLock) { 136b67a637e60c356ab520050b2bd09a95ae47f3017Svetoslav String prefix = (args.length > 0) ? args[0] : ""; 137dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov String tab = " "; 138dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 139dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov pw.append(prefix).append("print jobs:").println(); 140dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov final int printJobCount = mPrintJobs.size(); 141dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov for (int i = 0; i < printJobCount; i++) { 142dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov PrintJobInfo printJob = mPrintJobs.get(i); 143dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov pw.append(prefix).append(tab).append(printJob.toString()); 144dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov pw.println(); 145dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 146dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 147dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov pw.append(prefix).append("print job files:").println(); 148dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov File[] files = getFilesDir().listFiles(); 149dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov if (files != null) { 150dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov final int fileCount = files.length; 151dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov for (int i = 0; i < fileCount; i++) { 152dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov File file = files[i]; 153dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov if (file.isFile() && file.getName().startsWith(PRINT_JOB_FILE_PREFIX)) { 154dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov pw.append(prefix).append(tab).append(file.getName()).println(); 155dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 156dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 157dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 158dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 159dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 160dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 161269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void sendOnPrintJobQueued(PrintJobInfo printJob) { 162269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Message message = mHandlerCaller.obtainMessageO( 163269403b032f965ff3847eb982c2f697229dc5a92Svetoslav HandlerCallerCallback.MSG_ON_PRINT_JOB_QUEUED, printJob); 164269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mHandlerCaller.executeOrSendMessage(message); 165269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 166269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 167269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void sendOnAllPrintJobsForServiceHandled(ComponentName service) { 168269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Message message = mHandlerCaller.obtainMessageO( 169269403b032f965ff3847eb982c2f697229dc5a92Svetoslav HandlerCallerCallback.MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED, service); 170269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mHandlerCaller.executeOrSendMessage(message); 171269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 172269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 173269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void sendOnAllPrintJobsHandled() { 174269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Message message = mHandlerCaller.obtainMessage( 175269403b032f965ff3847eb982c2f697229dc5a92Svetoslav HandlerCallerCallback.MSG_ON_ALL_PRINT_JOBS_HANDLED); 176269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mHandlerCaller.executeOrSendMessage(message); 177269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 178269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 179269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private final class HandlerCallerCallback implements HandlerCaller.Callback { 180704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov public static final int MSG_SET_CLIENT = 1; 1817bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final int MSG_ON_PRINT_JOB_QUEUED = 2; 1827bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final int MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED = 3; 1837bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 4; 1847bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final int MSG_CHECK_ALL_PRINTJOBS_HANDLED = 5; 1857bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final int MSG_ON_PRINT_JOB_STATE_CHANGED = 6; 1864b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 188269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public void executeMessage(Message message) { 189835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov switch (message.what) { 190835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov case MSG_SET_CLIENT: { 191269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 192269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mClient = (IPrintSpoolerClient) message.obj; 193269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (mClient != null) { 194269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Message msg = mHandlerCaller.obtainMessage( 195269403b032f965ff3847eb982c2f697229dc5a92Svetoslav HandlerCallerCallback.MSG_CHECK_ALL_PRINTJOBS_HANDLED); 196269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mHandlerCaller.sendMessageDelayed(msg, 197269403b032f965ff3847eb982c2f697229dc5a92Svetoslav CHECK_ALL_PRINTJOBS_HANDLED_DELAY); 198269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 199835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 200835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } break; 201835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov 202835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov case MSG_ON_PRINT_JOB_QUEUED: { 203835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov PrintJobInfo printJob = (PrintJobInfo) message.obj; 204835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov if (mClient != null) { 205835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov try { 206835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov mClient.onPrintJobQueued(printJob); 207835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } catch (RemoteException re) { 208835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov Slog.e(LOG_TAG, "Error notify for a queued print job.", re); 209835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 210835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 211835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } break; 212835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov 213835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov case MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED: { 214835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov ComponentName service = (ComponentName) message.obj; 215835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov if (mClient != null) { 216835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov try { 217835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov mClient.onAllPrintJobsForServiceHandled(service); 218835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } catch (RemoteException re) { 219835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov Slog.e(LOG_TAG, "Error notify for all print jobs per service" 220835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov + " handled.", re); 221835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 222835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 223835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } break; 224835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov 225835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov case MSG_ON_ALL_PRINT_JOBS_HANDLED: { 226835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov if (mClient != null) { 227835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov try { 228835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov mClient.onAllPrintJobsHandled(); 229835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } catch (RemoteException re) { 230835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov Slog.e(LOG_TAG, "Error notify for all print job handled.", re); 231835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 232835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 233835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } break; 234835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov 235835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov case MSG_CHECK_ALL_PRINTJOBS_HANDLED: { 236269403b032f965ff3847eb982c2f697229dc5a92Svetoslav checkAllPrintJobsHandled(); 237269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } break; 238704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 239704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov case MSG_ON_PRINT_JOB_STATE_CHANGED: { 240704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (mClient != null) { 241dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov PrintJobInfo printJob = (PrintJobInfo) message.obj; 242704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov try { 243dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov mClient.onPrintJobStateChanged(printJob); 244704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } catch (RemoteException re) { 245704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov Slog.e(LOG_TAG, "Error notify for print job state change.", re); 246704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 247704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 248704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } break; 2494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 252269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 253269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public List<PrintJobInfo> getPrintJobInfos(ComponentName componentName, 254269403b032f965ff3847eb982c2f697229dc5a92Svetoslav int state, int appId) { 255269403b032f965ff3847eb982c2f697229dc5a92Svetoslav List<PrintJobInfo> foundPrintJobs = null; 256269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 257269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int printJobCount = mPrintJobs.size(); 258269403b032f965ff3847eb982c2f697229dc5a92Svetoslav for (int i = 0; i < printJobCount; i++) { 259269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = mPrintJobs.get(i); 260269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrinterId printerId = printJob.getPrinterId(); 261269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final boolean sameComponent = (componentName == null 262269403b032f965ff3847eb982c2f697229dc5a92Svetoslav || (printerId != null 263269403b032f965ff3847eb982c2f697229dc5a92Svetoslav && componentName.equals(printerId.getServiceName()))); 264269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final boolean sameAppId = appId == PrintManager.APP_ID_ANY 265269403b032f965ff3847eb982c2f697229dc5a92Svetoslav || printJob.getAppId() == appId; 266269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final boolean sameState = (state == printJob.getState()) 267269403b032f965ff3847eb982c2f697229dc5a92Svetoslav || (state == PrintJobInfo.STATE_ANY) 268269403b032f965ff3847eb982c2f697229dc5a92Svetoslav || (state == PrintJobInfo.STATE_ANY_VISIBLE_TO_CLIENTS 269d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov && isStateVisibleToUser(printJob.getState())) 270d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov || (state == PrintJobInfo.STATE_ANY_ACTIVE 2719b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov && isActiveState(printJob.getState())) 2729b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov || (state == PrintJobInfo.STATE_ANY_SCHEDULED 2739b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov && isScheduledState(printJob.getState())); 274269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (sameComponent && sameAppId && sameState) { 275269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (foundPrintJobs == null) { 276269403b032f965ff3847eb982c2f697229dc5a92Svetoslav foundPrintJobs = new ArrayList<PrintJobInfo>(); 277269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 278269403b032f965ff3847eb982c2f697229dc5a92Svetoslav foundPrintJobs.add(printJob); 279269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 280269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 281269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 282269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return foundPrintJobs; 283269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 284269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 285d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov private boolean isStateVisibleToUser(int state) { 286d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov return (isActiveState(state) && (state == PrintJobInfo.STATE_FAILED 2872fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav || state == PrintJobInfo.STATE_COMPLETED || state == PrintJobInfo.STATE_CANCELED 2882fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav || state == PrintJobInfo.STATE_BLOCKED)); 289d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov } 290d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov 2912fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId) { 292269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 293269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int printJobCount = mPrintJobs.size(); 294269403b032f965ff3847eb982c2f697229dc5a92Svetoslav for (int i = 0; i < printJobCount; i++) { 295269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = mPrintJobs.get(i); 2962fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav if (printJob.getId().equals(printJobId) 297269403b032f965ff3847eb982c2f697229dc5a92Svetoslav && (appId == PrintManager.APP_ID_ANY 298269403b032f965ff3847eb982c2f697229dc5a92Svetoslav || appId == printJob.getAppId())) { 299269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return printJob; 300269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 301269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 302269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return null; 303269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 304269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 305269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 3062fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public void createPrintJob(PrintJobInfo printJob) { 307269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 308269403b032f965ff3847eb982c2f697229dc5a92Svetoslav addPrintJobLocked(printJob); 309dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov setPrintJobState(printJob.getId(), PrintJobInfo.STATE_CREATED, null); 3107bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 3117bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav Message message = mHandlerCaller.obtainMessageO( 3127bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED, 3137bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav printJob); 3147bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav mHandlerCaller.executeOrSendMessage(message); 315269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 316269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 317269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 318269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void handleReadPrintJobsLocked() { 319dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov // Make a map with the files for a print job since we may have 320dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov // to delete some. One example of getting orphan files if the 321dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov // spooler crashes while constructing a print job. We do not 322dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov // persist partially populated print jobs under construction to 323dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov // avoid special handling for various attributes missing. 324dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov ArrayMap<PrintJobId, File> fileForJobMap = null; 325dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov File[] files = getFilesDir().listFiles(); 326dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov if (files != null) { 327dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov final int fileCount = files.length; 328dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov for (int i = 0; i < fileCount; i++) { 329dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov File file = files[i]; 330dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov if (file.isFile() && file.getName().startsWith(PRINT_JOB_FILE_PREFIX)) { 331dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov if (fileForJobMap == null) { 332dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov fileForJobMap = new ArrayMap<PrintJobId, File>(); 333dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 3342b40c83ae1ec17ea9371c3fd3ac6c79c156faa1dSvetoslav Ganov String printJobIdString = file.getName().substring( 3352b40c83ae1ec17ea9371c3fd3ac6c79c156faa1dSvetoslav Ganov PRINT_JOB_FILE_PREFIX.length(), 3362b40c83ae1ec17ea9371c3fd3ac6c79c156faa1dSvetoslav Ganov file.getName().indexOf('.')); 337dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov PrintJobId printJobId = PrintJobId.unflattenFromString( 338dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov printJobIdString); 339dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov fileForJobMap.put(printJobId, file); 340dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 341dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 342dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 343dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 344269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int printJobCount = mPrintJobs.size(); 345269403b032f965ff3847eb982c2f697229dc5a92Svetoslav for (int i = 0; i < printJobCount; i++) { 346269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = mPrintJobs.get(i); 347269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 348dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov // We want to have only the orphan files at the end. 349dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov if (fileForJobMap != null) { 350dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov fileForJobMap.remove(printJob.getId()); 351dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 352dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 353269403b032f965ff3847eb982c2f697229dc5a92Svetoslav switch (printJob.getState()) { 354269403b032f965ff3847eb982c2f697229dc5a92Svetoslav case PrintJobInfo.STATE_QUEUED: 355d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov case PrintJobInfo.STATE_STARTED: 356d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov case PrintJobInfo.STATE_BLOCKED: { 357d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov // We have a print job that was queued or started or blocked in 358d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov // the past but the device battery died or a crash occurred. In 359d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov // this case we assume the print job failed and let the user 360d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov // decide whether to restart the job or just cancel it. 361269403b032f965ff3847eb982c2f697229dc5a92Svetoslav setPrintJobState(printJob.getId(), PrintJobInfo.STATE_FAILED, 362269403b032f965ff3847eb982c2f697229dc5a92Svetoslav getString(R.string.no_connection_to_printer)); 3632fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } break; 364269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 365269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 366dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 367a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov if (!mPrintJobs.isEmpty()) { 368a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov // Update the notification. 369a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov mNotificationController.onUpdateNotifications(mPrintJobs); 370a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } 371a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov 372dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov // Delete the orphan files. 373dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov if (fileForJobMap != null) { 374dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov final int orphanFileCount = fileForJobMap.size(); 375dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov for (int i = 0; i < orphanFileCount; i++) { 376dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov File file = fileForJobMap.valueAt(i); 377dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov file.delete(); 378dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 379dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 380269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 381269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 382269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public void checkAllPrintJobsHandled() { 383269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 384269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (!hasActivePrintJobsLocked()) { 385269403b032f965ff3847eb982c2f697229dc5a92Svetoslav notifyOnAllPrintJobsHandled(); 386269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 387269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 388269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 389269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 3902fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public void writePrintJobData(final ParcelFileDescriptor fd, final PrintJobId printJobId) { 391269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final PrintJobInfo printJob; 392269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 393269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); 394269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 395269403b032f965ff3847eb982c2f697229dc5a92Svetoslav new AsyncTask<Void, Void, Void>() { 396269403b032f965ff3847eb982c2f697229dc5a92Svetoslav @Override 397269403b032f965ff3847eb982c2f697229dc5a92Svetoslav protected Void doInBackground(Void... params) { 398269403b032f965ff3847eb982c2f697229dc5a92Svetoslav FileInputStream in = null; 399269403b032f965ff3847eb982c2f697229dc5a92Svetoslav FileOutputStream out = null; 400269403b032f965ff3847eb982c2f697229dc5a92Svetoslav try { 401269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printJob != null) { 402269403b032f965ff3847eb982c2f697229dc5a92Svetoslav File file = generateFileForPrintJob(printJobId); 403269403b032f965ff3847eb982c2f697229dc5a92Svetoslav in = new FileInputStream(file); 404269403b032f965ff3847eb982c2f697229dc5a92Svetoslav out = new FileOutputStream(fd.getFileDescriptor()); 405269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 406269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final byte[] buffer = new byte[8192]; 407269403b032f965ff3847eb982c2f697229dc5a92Svetoslav while (true) { 408269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int readByteCount = in.read(buffer); 409269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (readByteCount < 0) { 410269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return null; 411269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 412269403b032f965ff3847eb982c2f697229dc5a92Svetoslav out.write(buffer, 0, readByteCount); 413269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 414269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (FileNotFoundException fnfe) { 415269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.e(LOG_TAG, "Error writing print job data!", fnfe); 416269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (IOException ioe) { 417269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.e(LOG_TAG, "Error writing print job data!", ioe); 418269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } finally { 419269403b032f965ff3847eb982c2f697229dc5a92Svetoslav IoUtils.closeQuietly(in); 420269403b032f965ff3847eb982c2f697229dc5a92Svetoslav IoUtils.closeQuietly(out); 421269403b032f965ff3847eb982c2f697229dc5a92Svetoslav IoUtils.closeQuietly(fd); 422269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 423269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.i(LOG_TAG, "[END WRITE]"); 424269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return null; 425269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 426269403b032f965ff3847eb982c2f697229dc5a92Svetoslav }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null); 427269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 428269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 4292fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public File generateFileForPrintJob(PrintJobId printJobId) { 430dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov return new File(getFilesDir(), PRINT_JOB_FILE_PREFIX 4312fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav + printJobId.flattenToString() + "." + PRINT_FILE_EXTENSION); 432269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 433269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 434269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void addPrintJobLocked(PrintJobInfo printJob) { 435269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mPrintJobs.add(printJob); 436269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (DEBUG_PRINT_JOB_LIFECYCLE) { 437269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.i(LOG_TAG, "[ADD] " + printJob); 438269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 439269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 440269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 4412fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav private void removeObsoletePrintJobs() { 4422fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav synchronized (mLock) { 4432fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav final int printJobCount = mPrintJobs.size(); 4442fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav for (int i = printJobCount - 1; i >= 0; i--) { 4452fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav PrintJobInfo printJob = mPrintJobs.get(i); 4462fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav if (isObsoleteState(printJob.getState())) { 4472fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav mPrintJobs.remove(i); 4482fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav if (DEBUG_PRINT_JOB_LIFECYCLE) { 4492fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav Slog.i(LOG_TAG, "[REMOVE] " + printJob.getId().flattenToString()); 4502fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 4512fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav removePrintJobFileLocked(printJob.getId()); 4522fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 4532fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 4542fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav mPersistanceManager.writeStateLocked(); 4552fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 4562fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 4572fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav 4582fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav private void removePrintJobFileLocked(PrintJobId printJobId) { 4592fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav File file = generateFileForPrintJob(printJobId); 4602fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav if (file.exists()) { 4612fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav file.delete(); 462269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (DEBUG_PRINT_JOB_LIFECYCLE) { 463dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov Slog.i(LOG_TAG, "[REMOVE FILE FOR] " + printJobId); 464269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 465269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 466269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 467269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 4682fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public boolean setPrintJobState(PrintJobId printJobId, int state, String error) { 469269403b032f965ff3847eb982c2f697229dc5a92Svetoslav boolean success = false; 470269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 471269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 472269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); 473269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printJob != null) { 474704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov final int oldState = printJob.getState(); 475704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (oldState == state) { 476704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov return false; 477704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 478704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 479269403b032f965ff3847eb982c2f697229dc5a92Svetoslav success = true; 480269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 481269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setState(state); 482d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov printJob.setStateReason(error); 483a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov printJob.setCancelling(false); 484269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 485269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (DEBUG_PRINT_JOB_LIFECYCLE) { 486269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.i(LOG_TAG, "[STATE CHANGED] " + printJob); 487269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 488269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 489269403b032f965ff3847eb982c2f697229dc5a92Svetoslav switch (state) { 490269403b032f965ff3847eb982c2f697229dc5a92Svetoslav case PrintJobInfo.STATE_COMPLETED: 491269403b032f965ff3847eb982c2f697229dc5a92Svetoslav case PrintJobInfo.STATE_CANCELED: 492dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov mPrintJobs.remove(printJob); 4932fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav removePrintJobFileLocked(printJob.getId()); 494269403b032f965ff3847eb982c2f697229dc5a92Svetoslav // $fall-through$ 495269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 496269403b032f965ff3847eb982c2f697229dc5a92Svetoslav case PrintJobInfo.STATE_FAILED: { 497269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrinterId printerId = printJob.getPrinterId(); 498269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printerId != null) { 499269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ComponentName service = printerId.getServiceName(); 500269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (!hasActivePrintJobsForServiceLocked(service)) { 501269403b032f965ff3847eb982c2f697229dc5a92Svetoslav sendOnAllPrintJobsForServiceHandled(service); 502269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 503269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 504269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } break; 505269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 506269403b032f965ff3847eb982c2f697229dc5a92Svetoslav case PrintJobInfo.STATE_QUEUED: { 507269403b032f965ff3847eb982c2f697229dc5a92Svetoslav sendOnPrintJobQueued(new PrintJobInfo(printJob)); 508269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } break; 509269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 510269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 511269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (shouldPersistPrintJob(printJob)) { 512269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mPersistanceManager.writeStateLocked(); 513269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 514269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 515269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (!hasActivePrintJobsLocked()) { 516269403b032f965ff3847eb982c2f697229dc5a92Svetoslav notifyOnAllPrintJobsHandled(); 517269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 518704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 519dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov Message message = mHandlerCaller.obtainMessageO( 520704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED, 521dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov printJob); 522704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov mHandlerCaller.executeOrSendMessage(message); 523a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov 524a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov mNotificationController.onUpdateNotifications(mPrintJobs); 525269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 526269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 527269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 528269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return success; 529269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 530269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 531269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public boolean hasActivePrintJobsLocked() { 532269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int printJobCount = mPrintJobs.size(); 533269403b032f965ff3847eb982c2f697229dc5a92Svetoslav for (int i = 0; i < printJobCount; i++) { 534269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = mPrintJobs.get(i); 535269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (isActiveState(printJob.getState())) { 536269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return true; 537269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 538269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 539269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 540269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 541269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 542269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public boolean hasActivePrintJobsForServiceLocked(ComponentName service) { 543269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int printJobCount = mPrintJobs.size(); 544269403b032f965ff3847eb982c2f697229dc5a92Svetoslav for (int i = 0; i < printJobCount; i++) { 545269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = mPrintJobs.get(i); 546269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (isActiveState(printJob.getState()) 547269403b032f965ff3847eb982c2f697229dc5a92Svetoslav && printJob.getPrinterId().getServiceName().equals(service)) { 548269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return true; 549269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 550269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 551269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 552269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 553269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 5542fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav private boolean isObsoleteState(int printJobState) { 5552fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav return (isTeminalState(printJobState) 5562fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav || printJobState == PrintJobInfo.STATE_QUEUED); 5572fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 5582fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav 5599b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov private boolean isScheduledState(int printJobState) { 5609b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov return printJobState == PrintJobInfo.STATE_QUEUED 5619b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov || printJobState == PrintJobInfo.STATE_STARTED 5629b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov || printJobState == PrintJobInfo.STATE_BLOCKED; 5639b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov } 5649b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov 565269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private boolean isActiveState(int printJobState) { 566269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return printJobState == PrintJobInfo.STATE_CREATED 567269403b032f965ff3847eb982c2f697229dc5a92Svetoslav || printJobState == PrintJobInfo.STATE_QUEUED 568d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov || printJobState == PrintJobInfo.STATE_STARTED 569d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov || printJobState == PrintJobInfo.STATE_BLOCKED; 570269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 571269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 5722fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav private boolean isTeminalState(int printJobState) { 5732fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav return printJobState == PrintJobInfo.STATE_COMPLETED 5742fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav || printJobState == PrintJobInfo.STATE_CANCELED; 5752fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 5762fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav 5772fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public boolean setPrintJobTag(PrintJobId printJobId, String tag) { 578269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 579269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); 580269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printJob != null) { 581269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String printJobTag = printJob.getTag(); 582269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printJobTag == null) { 583269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (tag == null) { 584269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 585269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 586269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } else if (printJobTag.equals(tag)) { 587269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 588269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 589269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setTag(tag); 590269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (shouldPersistPrintJob(printJob)) { 591269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mPersistanceManager.writeStateLocked(); 592269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 593269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return true; 594269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 595269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 596269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 597269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 598269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 599a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov public void setPrintJobCancelling(PrintJobId printJobId, boolean cancelling) { 600a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov synchronized (mLock) { 601a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); 602a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov if (printJob != null) { 603a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov printJob.setCancelling(cancelling); 604a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov if (shouldPersistPrintJob(printJob)) { 605a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov mPersistanceManager.writeStateLocked(); 606a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } 607a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov mNotificationController.onUpdateNotifications(mPrintJobs); 608a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov 609a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov Message message = mHandlerCaller.obtainMessageO( 610a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED, 611a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov printJob); 612a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov mHandlerCaller.executeOrSendMessage(message); 613a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } 614a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } 615a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } 616a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov 6172fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public void setPrintJobCopiesNoPersistence(PrintJobId printJobId, int copies) { 618269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 619269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); 620269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printJob != null) { 621269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setCopies(copies); 622269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 623269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 624269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 625269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 6262fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public void setPrintJobPrintDocumentInfoNoPersistence(PrintJobId printJobId, 6272fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav PrintDocumentInfo info) { 628269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 629269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); 630269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printJob != null) { 631269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setDocumentInfo(info); 632269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 633269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 634269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 635269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 6362fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public void setPrintJobAttributesNoPersistence(PrintJobId printJobId, 6372fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav PrintAttributes attributes) { 638269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 639269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); 640269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printJob != null) { 641269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setAttributes(attributes); 642269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 643269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 644269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 645269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 6462fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public void setPrintJobPrinterNoPersistence(PrintJobId printJobId, PrinterInfo printer) { 647269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 648269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); 649269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printJob != null) { 650269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setPrinterId(printer.getId()); 651269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setPrinterName(printer.getName()); 652269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 653269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 654269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 655269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 6562fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public void setPrintJobPagesNoPersistence(PrintJobId printJobId, PageRange[] pages) { 657269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 658269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); 659269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printJob != null) { 660269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setPages(pages); 661269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 662269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 663269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 664269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 665269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private boolean shouldPersistPrintJob(PrintJobInfo printJob) { 666269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return printJob.getState() >= PrintJobInfo.STATE_QUEUED; 667269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 668269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 669269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void notifyOnAllPrintJobsHandled() { 670269403b032f965ff3847eb982c2f697229dc5a92Svetoslav // This has to run on the tread that is persisting the current state 671269403b032f965ff3847eb982c2f697229dc5a92Svetoslav // since this call may result in the system unbinding from the spooler 672269403b032f965ff3847eb982c2f697229dc5a92Svetoslav // and as a result the spooler process may get killed before the write 673269403b032f965ff3847eb982c2f697229dc5a92Svetoslav // completes. 674269403b032f965ff3847eb982c2f697229dc5a92Svetoslav new AsyncTask<Void, Void, Void>() { 675269403b032f965ff3847eb982c2f697229dc5a92Svetoslav @Override 676269403b032f965ff3847eb982c2f697229dc5a92Svetoslav protected Void doInBackground(Void... params) { 677269403b032f965ff3847eb982c2f697229dc5a92Svetoslav sendOnAllPrintJobsHandled(); 678269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return null; 679269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 680269403b032f965ff3847eb982c2f697229dc5a92Svetoslav }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null); 681269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 682269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 683269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private final class PersistenceManager { 684269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String PERSIST_FILE_NAME = "print_spooler_state.xml"; 685269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 686269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_SPOOLER = "spooler"; 687269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_JOB = "job"; 688269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 689269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_PRINTER_ID = "printerId"; 690269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_PAGE_RANGE = "pageRange"; 691269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_ATTRIBUTES = "attributes"; 692269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_DOCUMENT_INFO = "documentInfo"; 693269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 694269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_ID = "id"; 695269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_LABEL = "label"; 696773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav private static final String ATTR_LABEL_RES_ID = "labelResId"; 697773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav private static final String ATTR_PACKAGE_NAME = "packageName"; 698269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_STATE = "state"; 699269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_APP_ID = "appId"; 700269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_TAG = "tag"; 701704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov private static final String ATTR_CREATION_TIME = "creationTime"; 702269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_COPIES = "copies"; 703704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov private static final String ATTR_PRINTER_NAME = "printerName"; 704704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov private static final String ATTR_STATE_REASON = "stateReason"; 705a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov private static final String ATTR_CANCELLING = "cancelling"; 706269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 707269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_MEDIA_SIZE = "mediaSize"; 708269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_RESOLUTION = "resolution"; 709269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_MARGINS = "margins"; 710269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 711269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_COLOR_MODE = "colorMode"; 712269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 713704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov private static final String ATTR_LOCAL_ID = "localId"; 714269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_SERVICE_NAME = "serviceName"; 715269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 716269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_WIDTH_MILS = "widthMils"; 717269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_HEIGHT_MILS = "heightMils"; 718269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 719269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_HORIZONTAL_DPI = "horizontalDip"; 720269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_VERTICAL_DPI = "verticalDpi"; 721269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 722269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_LEFT_MILS = "leftMils"; 723269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_TOP_MILS = "topMils"; 724269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_RIGHT_MILS = "rightMils"; 725269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_BOTTOM_MILS = "bottomMils"; 726269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 727269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_START = "start"; 728269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_END = "end"; 729269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 730269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_NAME = "name"; 731269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_PAGE_COUNT = "pageCount"; 732269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_CONTENT_TYPE = "contentType"; 733269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 734269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private final AtomicFile mStatePersistFile; 735269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 736269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private boolean mWriteStateScheduled; 737269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 738269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private PersistenceManager() { 739269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mStatePersistFile = new AtomicFile(new File(getFilesDir(), 740269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PERSIST_FILE_NAME)); 741269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 742269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 743269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public void writeStateLocked() { 744269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (!PERSISTNECE_MANAGER_ENABLED) { 745269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return; 746269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 747269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (mWriteStateScheduled) { 748269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return; 749269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 750269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mWriteStateScheduled = true; 751269403b032f965ff3847eb982c2f697229dc5a92Svetoslav new AsyncTask<Void, Void, Void>() { 752269403b032f965ff3847eb982c2f697229dc5a92Svetoslav @Override 753269403b032f965ff3847eb982c2f697229dc5a92Svetoslav protected Void doInBackground(Void... params) { 754269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 755269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mWriteStateScheduled = false; 756269403b032f965ff3847eb982c2f697229dc5a92Svetoslav doWriteStateLocked(); 757269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 758269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return null; 759269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 760269403b032f965ff3847eb982c2f697229dc5a92Svetoslav }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null); 761269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 762269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 763269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void doWriteStateLocked() { 764269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (DEBUG_PERSISTENCE) { 765269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.i(LOG_TAG, "[PERSIST START]"); 766269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 767269403b032f965ff3847eb982c2f697229dc5a92Svetoslav FileOutputStream out = null; 768269403b032f965ff3847eb982c2f697229dc5a92Svetoslav try { 769269403b032f965ff3847eb982c2f697229dc5a92Svetoslav out = mStatePersistFile.startWrite(); 770269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 771269403b032f965ff3847eb982c2f697229dc5a92Svetoslav XmlSerializer serializer = new FastXmlSerializer(); 772269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.setOutput(out, "utf-8"); 773269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startDocument(null, true); 774269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_SPOOLER); 775269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 776269403b032f965ff3847eb982c2f697229dc5a92Svetoslav List<PrintJobInfo> printJobs = mPrintJobs; 777269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 778269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int printJobCount = printJobs.size(); 779269403b032f965ff3847eb982c2f697229dc5a92Svetoslav for (int j = 0; j < printJobCount; j++) { 780269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = printJobs.get(j); 781269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 782269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_JOB); 783269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 7842fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav serializer.attribute(null, ATTR_ID, printJob.getId().flattenToString()); 785269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_LABEL, printJob.getLabel().toString()); 786269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_STATE, String.valueOf(printJob.getState())); 787269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_APP_ID, String.valueOf(printJob.getAppId())); 788269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String tag = printJob.getTag(); 789269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (tag != null) { 790269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_TAG, tag); 791269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 792704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov serializer.attribute(null, ATTR_CREATION_TIME, String.valueOf( 793704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov printJob.getCreationTime())); 794269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_COPIES, String.valueOf(printJob.getCopies())); 795704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov String printerName = printJob.getPrinterName(); 796704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (!TextUtils.isEmpty(printerName)) { 797704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov serializer.attribute(null, ATTR_PRINTER_NAME, printerName); 798704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 799704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov String stateReason = printJob.getStateReason(); 800704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (!TextUtils.isEmpty(stateReason)) { 801704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov serializer.attribute(null, ATTR_STATE_REASON, stateReason); 802704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 803a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov serializer.attribute(null, ATTR_CANCELLING, String.valueOf( 804a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov printJob.isCancelling())); 805269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 806269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrinterId printerId = printJob.getPrinterId(); 807269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printerId != null) { 808269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_PRINTER_ID); 809269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_LOCAL_ID, printerId.getLocalId()); 810269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_SERVICE_NAME, printerId.getServiceName() 811269403b032f965ff3847eb982c2f697229dc5a92Svetoslav .flattenToString()); 812269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_PRINTER_ID); 813269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 814269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 815269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PageRange[] pages = printJob.getPages(); 816269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (pages != null) { 817269403b032f965ff3847eb982c2f697229dc5a92Svetoslav for (int i = 0; i < pages.length; i++) { 818269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_PAGE_RANGE); 819269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_START, String.valueOf( 820269403b032f965ff3847eb982c2f697229dc5a92Svetoslav pages[i].getStart())); 821269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_END, String.valueOf( 822269403b032f965ff3847eb982c2f697229dc5a92Svetoslav pages[i].getEnd())); 823269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_PAGE_RANGE); 824269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 825269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 826269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 827269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintAttributes attributes = printJob.getAttributes(); 828269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (attributes != null) { 829269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_ATTRIBUTES); 830269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 831269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int colorMode = attributes.getColorMode(); 832269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_COLOR_MODE, 833269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String.valueOf(colorMode)); 834269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 835269403b032f965ff3847eb982c2f697229dc5a92Svetoslav MediaSize mediaSize = attributes.getMediaSize(); 836269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (mediaSize != null) { 837269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_MEDIA_SIZE); 838269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_ID, mediaSize.getId()); 839269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_WIDTH_MILS, String.valueOf( 840269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mediaSize.getWidthMils())); 841269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_HEIGHT_MILS, String.valueOf( 842269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mediaSize.getHeightMils())); 843a76233ae845da4bc9e3bcd89821701a747215e7bSvetoslav // We prefer to store only the package name and 844a76233ae845da4bc9e3bcd89821701a747215e7bSvetoslav // resource id and fallback to the label. 845a76233ae845da4bc9e3bcd89821701a747215e7bSvetoslav if (!TextUtils.isEmpty(mediaSize.mPackageName) 846773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav && mediaSize.mLabelResId > 0) { 847773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav serializer.attribute(null, ATTR_PACKAGE_NAME, 848773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav mediaSize.mPackageName); 849773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav serializer.attribute(null, ATTR_LABEL_RES_ID, 850773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav String.valueOf(mediaSize.mLabelResId)); 851773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav } else { 852773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav serializer.attribute(null, ATTR_LABEL, 853773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav mediaSize.getLabel(getPackageManager())); 854773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav } 855269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_MEDIA_SIZE); 856269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 857269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 858269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Resolution resolution = attributes.getResolution(); 859269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (resolution != null) { 860269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_RESOLUTION); 861269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_ID, resolution.getId()); 862269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_HORIZONTAL_DPI, String.valueOf( 863269403b032f965ff3847eb982c2f697229dc5a92Svetoslav resolution.getHorizontalDpi())); 864269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_VERTICAL_DPI, String.valueOf( 865269403b032f965ff3847eb982c2f697229dc5a92Svetoslav resolution.getVerticalDpi())); 866c6066799ad130140159230d14451b429eb828755Svetoslav serializer.attribute(null, ATTR_LABEL, 867651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav resolution.getLabel()); 868269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_RESOLUTION); 869269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 870269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 871651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav Margins margins = attributes.getMinMargins(); 872269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (margins != null) { 873269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_MARGINS); 874269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_LEFT_MILS, String.valueOf( 875269403b032f965ff3847eb982c2f697229dc5a92Svetoslav margins.getLeftMils())); 876269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_TOP_MILS, String.valueOf( 877269403b032f965ff3847eb982c2f697229dc5a92Svetoslav margins.getTopMils())); 878269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_RIGHT_MILS, String.valueOf( 879269403b032f965ff3847eb982c2f697229dc5a92Svetoslav margins.getRightMils())); 880269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_BOTTOM_MILS, String.valueOf( 881269403b032f965ff3847eb982c2f697229dc5a92Svetoslav margins.getBottomMils())); 882269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_MARGINS); 883269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 884269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 885269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_ATTRIBUTES); 886269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 887269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 888269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintDocumentInfo documentInfo = printJob.getDocumentInfo(); 889269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (documentInfo != null) { 890269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_DOCUMENT_INFO); 891269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_NAME, documentInfo.getName()); 892269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_CONTENT_TYPE, String.valueOf( 893269403b032f965ff3847eb982c2f697229dc5a92Svetoslav documentInfo.getContentType())); 894269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_PAGE_COUNT, String.valueOf( 895269403b032f965ff3847eb982c2f697229dc5a92Svetoslav documentInfo.getPageCount())); 896269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_DOCUMENT_INFO); 897269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 898269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 899269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_JOB); 900269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 901269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (DEBUG_PERSISTENCE) { 902269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.i(LOG_TAG, "[PERSISTED] " + printJob); 903269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 904269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 905269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 906269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_SPOOLER); 907269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endDocument(); 908269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mStatePersistFile.finishWrite(out); 909269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (DEBUG_PERSISTENCE) { 910269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.i(LOG_TAG, "[PERSIST END]"); 911269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 912269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (IOException e) { 913269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.w(LOG_TAG, "Failed to write state, restoring backup.", e); 914269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mStatePersistFile.failWrite(out); 915269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } finally { 916269403b032f965ff3847eb982c2f697229dc5a92Svetoslav IoUtils.closeQuietly(out); 917269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 918269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 919269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 920269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public void readStateLocked() { 921269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (!PERSISTNECE_MANAGER_ENABLED) { 922269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return; 923269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 924269403b032f965ff3847eb982c2f697229dc5a92Svetoslav FileInputStream in = null; 925269403b032f965ff3847eb982c2f697229dc5a92Svetoslav try { 926269403b032f965ff3847eb982c2f697229dc5a92Svetoslav in = mStatePersistFile.openRead(); 927269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (FileNotFoundException e) { 928269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.i(LOG_TAG, "No existing print spooler state."); 929269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return; 930269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 931269403b032f965ff3847eb982c2f697229dc5a92Svetoslav try { 932269403b032f965ff3847eb982c2f697229dc5a92Svetoslav XmlPullParser parser = Xml.newPullParser(); 933269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.setInput(in, null); 934269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parseState(parser); 935269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (IllegalStateException ise) { 936269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.w(LOG_TAG, "Failed parsing ", ise); 937269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (NullPointerException npe) { 938269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.w(LOG_TAG, "Failed parsing ", npe); 939269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (NumberFormatException nfe) { 940269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.w(LOG_TAG, "Failed parsing ", nfe); 941269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (XmlPullParserException xppe) { 942269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.w(LOG_TAG, "Failed parsing ", xppe); 943269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (IOException ioe) { 944269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.w(LOG_TAG, "Failed parsing ", ioe); 945269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (IndexOutOfBoundsException iobe) { 946269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.w(LOG_TAG, "Failed parsing ", iobe); 947269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } finally { 948269403b032f965ff3847eb982c2f697229dc5a92Svetoslav IoUtils.closeQuietly(in); 949269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 950269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 951269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 952269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void parseState(XmlPullParser parser) 953269403b032f965ff3847eb982c2f697229dc5a92Svetoslav throws IOException, XmlPullParserException { 954269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 955269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 956269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.START_TAG, TAG_SPOOLER); 957269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 958269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 959269403b032f965ff3847eb982c2f697229dc5a92Svetoslav while (parsePrintJob(parser)) { 960269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 961269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 962269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 963269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 964269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_SPOOLER); 965269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 966269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 967269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private boolean parsePrintJob(XmlPullParser parser) 968269403b032f965ff3847eb982c2f697229dc5a92Svetoslav throws IOException, XmlPullParserException { 969269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 970269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (!accept(parser, XmlPullParser.START_TAG, TAG_JOB)) { 971269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 972269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 973269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 974269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = new PrintJobInfo(); 975269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 9762fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav PrintJobId printJobId = PrintJobId.unflattenFromString( 9772fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav parser.getAttributeValue(null, ATTR_ID)); 978269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setId(printJobId); 979269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String label = parser.getAttributeValue(null, ATTR_LABEL); 980269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setLabel(label); 981269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int state = Integer.parseInt(parser.getAttributeValue(null, ATTR_STATE)); 982269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setState(state); 983269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int appId = Integer.parseInt(parser.getAttributeValue(null, ATTR_APP_ID)); 984269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setAppId(appId); 985269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String tag = parser.getAttributeValue(null, ATTR_TAG); 986269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setTag(tag); 987704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov String creationTime = parser.getAttributeValue(null, ATTR_CREATION_TIME); 988704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov printJob.setCreationTime(Long.parseLong(creationTime)); 989269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String copies = parser.getAttributeValue(null, ATTR_COPIES); 990269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setCopies(Integer.parseInt(copies)); 991704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov String printerName = parser.getAttributeValue(null, ATTR_PRINTER_NAME); 992704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov printJob.setPrinterName(printerName); 993704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov String stateReason = parser.getAttributeValue(null, ATTR_STATE_REASON); 994704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov printJob.setStateReason(stateReason); 995a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov String cancelling = parser.getAttributeValue(null, ATTR_CANCELLING); 996a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov printJob.setCancelling(!TextUtils.isEmpty(cancelling) 997a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov ? Boolean.parseBoolean(cancelling) : false); 998269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 999269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1000269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1001269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1002269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (accept(parser, XmlPullParser.START_TAG, TAG_PRINTER_ID)) { 1003269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String localId = parser.getAttributeValue(null, ATTR_LOCAL_ID); 1004269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ComponentName service = ComponentName.unflattenFromString(parser.getAttributeValue( 1005269403b032f965ff3847eb982c2f697229dc5a92Svetoslav null, ATTR_SERVICE_NAME)); 1006269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setPrinterId(new PrinterId(service, localId)); 1007269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1008269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1009269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_PRINTER_ID); 1010269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1011269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1012269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1013269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1014269403b032f965ff3847eb982c2f697229dc5a92Svetoslav List<PageRange> pageRanges = null; 1015269403b032f965ff3847eb982c2f697229dc5a92Svetoslav while (accept(parser, XmlPullParser.START_TAG, TAG_PAGE_RANGE)) { 1016269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int start = Integer.parseInt(parser.getAttributeValue(null, ATTR_START)); 1017269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int end = Integer.parseInt(parser.getAttributeValue(null, ATTR_END)); 1018269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PageRange pageRange = new PageRange(start, end); 1019269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (pageRanges == null) { 1020269403b032f965ff3847eb982c2f697229dc5a92Svetoslav pageRanges = new ArrayList<PageRange>(); 1021269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1022269403b032f965ff3847eb982c2f697229dc5a92Svetoslav pageRanges.add(pageRange); 1023269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1024269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1025269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_PAGE_RANGE); 1026269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1027269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1028269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (pageRanges != null) { 1029269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PageRange[] pageRangesArray = new PageRange[pageRanges.size()]; 1030269403b032f965ff3847eb982c2f697229dc5a92Svetoslav pageRanges.toArray(pageRangesArray); 1031269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setPages(pageRangesArray); 1032269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1033269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1034269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1035269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (accept(parser, XmlPullParser.START_TAG, TAG_ATTRIBUTES)) { 1036269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1037269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintAttributes.Builder builder = new PrintAttributes.Builder(); 1038269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1039269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String colorMode = parser.getAttributeValue(null, ATTR_COLOR_MODE); 1040269403b032f965ff3847eb982c2f697229dc5a92Svetoslav builder.setColorMode(Integer.parseInt(colorMode)); 1041269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1042269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1043269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1044269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1045269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (accept(parser, XmlPullParser.START_TAG, TAG_MEDIA_SIZE)) { 1046269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String id = parser.getAttributeValue(null, ATTR_ID); 1047269403b032f965ff3847eb982c2f697229dc5a92Svetoslav label = parser.getAttributeValue(null, ATTR_LABEL); 1048269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int widthMils = Integer.parseInt(parser.getAttributeValue(null, 1049269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_WIDTH_MILS)); 1050269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int heightMils = Integer.parseInt(parser.getAttributeValue(null, 1051269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_HEIGHT_MILS)); 1052773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav String packageName = parser.getAttributeValue(null, ATTR_PACKAGE_NAME); 1053b206f1271d17164c3f2f65219eee7a0b4b4fa6dcSvetoslav String labelResIdString = parser.getAttributeValue(null, ATTR_LABEL_RES_ID); 1054b206f1271d17164c3f2f65219eee7a0b4b4fa6dcSvetoslav final int labelResId = (labelResIdString != null) 1055b206f1271d17164c3f2f65219eee7a0b4b4fa6dcSvetoslav ? Integer.parseInt(labelResIdString) : 0; 1056773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav label = parser.getAttributeValue(null, ATTR_LABEL); 1057773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav MediaSize mediaSize = new MediaSize(id, label, packageName, labelResId, 1058773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav widthMils, heightMils); 1059269403b032f965ff3847eb982c2f697229dc5a92Svetoslav builder.setMediaSize(mediaSize); 1060269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1061269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1062269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_MEDIA_SIZE); 1063269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1064269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1065269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1066269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1067269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (accept(parser, XmlPullParser.START_TAG, TAG_RESOLUTION)) { 1068269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String id = parser.getAttributeValue(null, ATTR_ID); 1069269403b032f965ff3847eb982c2f697229dc5a92Svetoslav label = parser.getAttributeValue(null, ATTR_LABEL); 1070269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int horizontalDpi = Integer.parseInt(parser.getAttributeValue(null, 1071269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_HORIZONTAL_DPI)); 1072269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int verticalDpi = Integer.parseInt(parser.getAttributeValue(null, 1073269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_VERTICAL_DPI)); 1074c6066799ad130140159230d14451b429eb828755Svetoslav Resolution resolution = new Resolution(id, label, horizontalDpi, verticalDpi); 1075269403b032f965ff3847eb982c2f697229dc5a92Svetoslav builder.setResolution(resolution); 1076269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1077269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1078269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_RESOLUTION); 1079269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1080269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1081269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1082269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1083269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (accept(parser, XmlPullParser.START_TAG, TAG_MARGINS)) { 1084269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int leftMils = Integer.parseInt(parser.getAttributeValue(null, 1085269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_LEFT_MILS)); 1086269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int topMils = Integer.parseInt(parser.getAttributeValue(null, 1087269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_TOP_MILS)); 1088269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int rightMils = Integer.parseInt(parser.getAttributeValue(null, 1089269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_RIGHT_MILS)); 1090269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int bottomMils = Integer.parseInt(parser.getAttributeValue(null, 1091269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_BOTTOM_MILS)); 1092269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Margins margins = new Margins(leftMils, topMils, rightMils, bottomMils); 1093651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav builder.setMinMargins(margins); 1094269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1095269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1096269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_MARGINS); 1097269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1098269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1099269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1100651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav printJob.setAttributes(builder.build()); 1101269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1102269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1103269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_ATTRIBUTES); 1104269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1105269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1106269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1107269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1108269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (accept(parser, XmlPullParser.START_TAG, TAG_DOCUMENT_INFO)) { 1109269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String name = parser.getAttributeValue(null, ATTR_NAME); 1110269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int pageCount = Integer.parseInt(parser.getAttributeValue(null, 1111269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_PAGE_COUNT)); 1112269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int contentType = Integer.parseInt(parser.getAttributeValue(null, 1113269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_CONTENT_TYPE)); 1114269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintDocumentInfo info = new PrintDocumentInfo.Builder(name) 1115269403b032f965ff3847eb982c2f697229dc5a92Svetoslav .setPageCount(pageCount) 1116651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav .setContentType(contentType).build(); 1117269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setDocumentInfo(info); 1118269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1119269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1120269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_DOCUMENT_INFO); 1121269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1122269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1123269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1124269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mPrintJobs.add(printJob); 1125269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1126269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (DEBUG_PERSISTENCE) { 1127269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.i(LOG_TAG, "[RESTORED] " + printJob); 1128269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1129269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1130269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1131269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_JOB); 1132269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1133269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return true; 1134269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1135269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1136269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void expect(XmlPullParser parser, int type, String tag) 1137269403b032f965ff3847eb982c2f697229dc5a92Svetoslav throws IOException, XmlPullParserException { 1138269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (!accept(parser, type, tag)) { 1139269403b032f965ff3847eb982c2f697229dc5a92Svetoslav throw new XmlPullParserException("Exepected event: " + type 1140269403b032f965ff3847eb982c2f697229dc5a92Svetoslav + " and tag: " + tag + " but got event: " + parser.getEventType() 1141269403b032f965ff3847eb982c2f697229dc5a92Svetoslav + " and tag:" + parser.getName()); 1142269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1143269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1144269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1145269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void skipEmptyTextTags(XmlPullParser parser) 1146269403b032f965ff3847eb982c2f697229dc5a92Svetoslav throws IOException, XmlPullParserException { 1147269403b032f965ff3847eb982c2f697229dc5a92Svetoslav while (accept(parser, XmlPullParser.TEXT, null) 1148269403b032f965ff3847eb982c2f697229dc5a92Svetoslav && "\n".equals(parser.getText())) { 1149269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1150269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1151269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1152269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1153269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private boolean accept(XmlPullParser parser, int type, String tag) 1154269403b032f965ff3847eb982c2f697229dc5a92Svetoslav throws IOException, XmlPullParserException { 1155269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (parser.getEventType() != type) { 1156269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 1157269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1158269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (tag != null) { 1159269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (!tag.equals(parser.getName())) { 1160269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 1161269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1162269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } else if (parser.getName() != null) { 1163269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 1164269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1165269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return true; 1166269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1167269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 11687bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 11697bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav final class PrintSpooler extends IPrintSpooler.Stub { 11707bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 11717bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void getPrintJobInfos(IPrintSpoolerCallbacks callback, 11727bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav ComponentName componentName, int state, int appId, int sequence) 11737bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav throws RemoteException { 11747bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav List<PrintJobInfo> printJobs = null; 11757bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav try { 11767bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav printJobs = PrintSpoolerService.this.getPrintJobInfos( 11777bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav componentName, state, appId); 11787bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } finally { 11797bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav callback.onGetPrintJobInfosResult(printJobs, sequence); 11807bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 11817bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 11827bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 11837bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 11847bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void getPrintJobInfo(PrintJobId printJobId, IPrintSpoolerCallbacks callback, 11857bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav int appId, int sequence) throws RemoteException { 11867bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav PrintJobInfo printJob = null; 11877bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav try { 11887bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav printJob = PrintSpoolerService.this.getPrintJobInfo(printJobId, appId); 11897bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } finally { 11907bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav callback.onGetPrintJobInfoResult(printJob, sequence); 11917bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 11927bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 11937bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 11947bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 11957bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void createPrintJob(PrintJobInfo printJob) { 11967bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav PrintSpoolerService.this.createPrintJob(printJob); 11977bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 11987bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 11997bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 12007bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void setPrintJobState(PrintJobId printJobId, int state, String error, 12017bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav IPrintSpoolerCallbacks callback, int sequece) throws RemoteException { 12027bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav boolean success = false; 12037bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav try { 12047bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav success = PrintSpoolerService.this.setPrintJobState( 12057bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav printJobId, state, error); 12067bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } finally { 12077bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav callback.onSetPrintJobStateResult(success, sequece); 12087bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12097bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12107bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 12117bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 12127bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void setPrintJobTag(PrintJobId printJobId, String tag, 12137bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav IPrintSpoolerCallbacks callback, int sequece) throws RemoteException { 12147bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav boolean success = false; 12157bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav try { 12167bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav success = PrintSpoolerService.this.setPrintJobTag(printJobId, tag); 12177bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } finally { 12187bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav callback.onSetPrintJobTagResult(success, sequece); 12197bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12207bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12217bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 12227bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 12237bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void writePrintJobData(ParcelFileDescriptor fd, PrintJobId printJobId) { 12247bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav PrintSpoolerService.this.writePrintJobData(fd, printJobId); 12257bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12267bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 12277bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 12287bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void setClient(IPrintSpoolerClient client) { 12297bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav Message message = mHandlerCaller.obtainMessageO( 12307bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav HandlerCallerCallback.MSG_SET_CLIENT, client); 12317bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav mHandlerCaller.executeOrSendMessage(message); 12327bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12337bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 12347bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 12357bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void removeObsoletePrintJobs() { 12367bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav PrintSpoolerService.this.removeObsoletePrintJobs(); 12377bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12387bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 12397bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 12407bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 12417bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav PrintSpoolerService.this.dump(fd, writer, args); 12427bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12437bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 12447bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 12457bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void setPrintJobCancelling(PrintJobId printJobId, boolean cancelling) { 12467bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav PrintSpoolerService.this.setPrintJobCancelling(printJobId, cancelling); 12477bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12487bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 12497bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public PrintSpoolerService getService() { 12507bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav return PrintSpoolerService.this; 12517bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12527bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov} 1254