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 17a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavpackage com.android.printspooler.model; 184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.app.Service; 204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.ComponentName; 21a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.content.Context; 224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.Intent; 23269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.os.AsyncTask; 24b4fda134761c9521a7e127db3806a07a18763b77Svetoslavimport android.os.Bundle; 254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.IBinder; 264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Message; 274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.ParcelFileDescriptor; 284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.RemoteException; 29a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.IPrintSpooler; 30a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.IPrintSpoolerCallbacks; 31835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganovimport android.print.IPrintSpoolerClient; 32269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PageRange; 334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.PrintAttributes; 34269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrintAttributes.Margins; 35269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrintAttributes.MediaSize; 36269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrintAttributes.Resolution; 37269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrintDocumentInfo; 382fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslavimport android.print.PrintJobId; 394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.PrintJobInfo; 40269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrintManager; 41269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrinterId; 42a76233ae845da4bc9e3bcd89821701a747215e7bSvetoslavimport android.text.TextUtils; 43dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganovimport android.util.ArrayMap; 44269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.util.AtomicFile; 45835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganovimport android.util.Log; 464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.util.Slog; 47269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.util.Xml; 484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 49269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport com.android.internal.os.HandlerCaller; 50269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport com.android.internal.util.FastXmlSerializer; 51a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport com.android.printspooler.R; 524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 532fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslavimport libcore.io.IoUtils; 542fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav 55269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport org.xmlpull.v1.XmlPullParser; 56269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport org.xmlpull.v1.XmlPullParserException; 57269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport org.xmlpull.v1.XmlSerializer; 58269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 59269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.io.File; 60dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganovimport java.io.FileDescriptor; 61269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.io.FileInputStream; 62269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.io.FileNotFoundException; 63269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.io.FileOutputStream; 64269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.io.IOException; 65dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganovimport java.io.PrintWriter; 66269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.util.ArrayList; 67835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganovimport java.util.List; 68835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov 694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/** 704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Service for exposing some of the {@link PrintSpooler} functionality to 714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * another process. 724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovpublic final class PrintSpoolerService extends Service { 744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 75269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String LOG_TAG = "PrintSpoolerService"; 76269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 77b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav private static final boolean DEBUG_PRINT_JOB_LIFECYCLE = false; 78269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 79c6066799ad130140159230d14451b429eb828755Svetoslav private static final boolean DEBUG_PERSISTENCE = false; 80269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 814237c92d850b7fb0fa0be15df94e4d1689e353fcSvet Ganov private static final boolean PERSISTENCE_MANAGER_ENABLED = true; 82269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 83835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov private static final long CHECK_ALL_PRINTJOBS_HANDLED_DELAY = 5000; 84835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov 85dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov private static final String PRINT_JOB_FILE_PREFIX = "print_job_"; 86dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 87269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String PRINT_FILE_EXTENSION = "pdf"; 88269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 89269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final Object sLock = new Object(); 90269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 91269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private final Object mLock = new Object(); 92269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 93a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private final List<PrintJobInfo> mPrintJobs = new ArrayList<>(); 94269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 95269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static PrintSpoolerService sInstance; 96269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 97835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov private IPrintSpoolerClient mClient; 984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 99269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private HandlerCaller mHandlerCaller; 100269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 101269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private PersistenceManager mPersistanceManager; 102269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 103269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private NotificationController mNotificationController; 104269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 105269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public static PrintSpoolerService peekInstance() { 106269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (sLock) { 107269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return sInstance; 108269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 109269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 1124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void onCreate() { 1134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov super.onCreate(); 114269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mHandlerCaller = new HandlerCaller(this, getMainLooper(), 115269403b032f965ff3847eb982c2f697229dc5a92Svetoslav new HandlerCallerCallback(), false); 116269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 117269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mPersistanceManager = new PersistenceManager(); 118269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mNotificationController = new NotificationController(PrintSpoolerService.this); 119269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 120269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 121269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mPersistanceManager.readStateLocked(); 122269403b032f965ff3847eb982c2f697229dc5a92Svetoslav handleReadPrintJobsLocked(); 123269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 124269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 125269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (sLock) { 126269403b032f965ff3847eb982c2f697229dc5a92Svetoslav sInstance = this; 127269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 1314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public IBinder onBind(Intent intent) { 1327bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav return new PrintSpooler(); 1334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 135dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov @Override 136dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 137dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov synchronized (mLock) { 138b67a637e60c356ab520050b2bd09a95ae47f3017Svetoslav String prefix = (args.length > 0) ? args[0] : ""; 139dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov String tab = " "; 140dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 141dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov pw.append(prefix).append("print jobs:").println(); 142dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov final int printJobCount = mPrintJobs.size(); 143dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov for (int i = 0; i < printJobCount; i++) { 144dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov PrintJobInfo printJob = mPrintJobs.get(i); 145dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov pw.append(prefix).append(tab).append(printJob.toString()); 146dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov pw.println(); 147dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 148dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 149dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov pw.append(prefix).append("print job files:").println(); 150dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov File[] files = getFilesDir().listFiles(); 151dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov if (files != null) { 152dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov final int fileCount = files.length; 153dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov for (int i = 0; i < fileCount; i++) { 154dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov File file = files[i]; 155dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov if (file.isFile() && file.getName().startsWith(PRINT_JOB_FILE_PREFIX)) { 156dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov pw.append(prefix).append(tab).append(file.getName()).println(); 157dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 158dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 159dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 160dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 161dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 162dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 163269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void sendOnPrintJobQueued(PrintJobInfo printJob) { 164269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Message message = mHandlerCaller.obtainMessageO( 165269403b032f965ff3847eb982c2f697229dc5a92Svetoslav HandlerCallerCallback.MSG_ON_PRINT_JOB_QUEUED, printJob); 166269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mHandlerCaller.executeOrSendMessage(message); 167269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 168269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 169269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void sendOnAllPrintJobsForServiceHandled(ComponentName service) { 170269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Message message = mHandlerCaller.obtainMessageO( 171269403b032f965ff3847eb982c2f697229dc5a92Svetoslav HandlerCallerCallback.MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED, service); 172269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mHandlerCaller.executeOrSendMessage(message); 173269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 174269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 175269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void sendOnAllPrintJobsHandled() { 176269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Message message = mHandlerCaller.obtainMessage( 177269403b032f965ff3847eb982c2f697229dc5a92Svetoslav HandlerCallerCallback.MSG_ON_ALL_PRINT_JOBS_HANDLED); 178269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mHandlerCaller.executeOrSendMessage(message); 179269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 180269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 181269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private final class HandlerCallerCallback implements HandlerCaller.Callback { 182704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov public static final int MSG_SET_CLIENT = 1; 1837bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final int MSG_ON_PRINT_JOB_QUEUED = 2; 1847bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final int MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED = 3; 1857bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 4; 1867bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final int MSG_CHECK_ALL_PRINTJOBS_HANDLED = 5; 1877bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final int MSG_ON_PRINT_JOB_STATE_CHANGED = 6; 1884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 190269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public void executeMessage(Message message) { 191835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov switch (message.what) { 192835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov case MSG_SET_CLIENT: { 193269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 194269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mClient = (IPrintSpoolerClient) message.obj; 195269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (mClient != null) { 196269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Message msg = mHandlerCaller.obtainMessage( 197269403b032f965ff3847eb982c2f697229dc5a92Svetoslav HandlerCallerCallback.MSG_CHECK_ALL_PRINTJOBS_HANDLED); 198269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mHandlerCaller.sendMessageDelayed(msg, 199269403b032f965ff3847eb982c2f697229dc5a92Svetoslav CHECK_ALL_PRINTJOBS_HANDLED_DELAY); 200269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 201835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 202835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } break; 203835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov 204835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov case MSG_ON_PRINT_JOB_QUEUED: { 205835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov PrintJobInfo printJob = (PrintJobInfo) message.obj; 206835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov if (mClient != null) { 207835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov try { 208835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov mClient.onPrintJobQueued(printJob); 209835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } catch (RemoteException re) { 210835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov Slog.e(LOG_TAG, "Error notify for a queued print job.", re); 211835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 212835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 213835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } break; 214835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov 215835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov case MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED: { 216835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov ComponentName service = (ComponentName) message.obj; 217835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov if (mClient != null) { 218835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov try { 219835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov mClient.onAllPrintJobsForServiceHandled(service); 220835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } catch (RemoteException re) { 221835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov Slog.e(LOG_TAG, "Error notify for all print jobs per service" 222835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov + " handled.", re); 223835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 224835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 225835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } break; 226835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov 227835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov case MSG_ON_ALL_PRINT_JOBS_HANDLED: { 228835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov if (mClient != null) { 229835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov try { 230835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov mClient.onAllPrintJobsHandled(); 231835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } catch (RemoteException re) { 232835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov Slog.e(LOG_TAG, "Error notify for all print job handled.", re); 233835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 234835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 235835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } break; 236835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov 237835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov case MSG_CHECK_ALL_PRINTJOBS_HANDLED: { 238269403b032f965ff3847eb982c2f697229dc5a92Svetoslav checkAllPrintJobsHandled(); 239269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } break; 240704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 241704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov case MSG_ON_PRINT_JOB_STATE_CHANGED: { 242704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (mClient != null) { 243dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov PrintJobInfo printJob = (PrintJobInfo) message.obj; 244704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov try { 245dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov mClient.onPrintJobStateChanged(printJob); 246704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } catch (RemoteException re) { 247704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov Slog.e(LOG_TAG, "Error notify for print job state change.", re); 248704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 249704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 250704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } break; 2514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 254269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 255269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public List<PrintJobInfo> getPrintJobInfos(ComponentName componentName, 256269403b032f965ff3847eb982c2f697229dc5a92Svetoslav int state, int appId) { 257269403b032f965ff3847eb982c2f697229dc5a92Svetoslav List<PrintJobInfo> foundPrintJobs = null; 258269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 259269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int printJobCount = mPrintJobs.size(); 260269403b032f965ff3847eb982c2f697229dc5a92Svetoslav for (int i = 0; i < printJobCount; i++) { 261269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = mPrintJobs.get(i); 262269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrinterId printerId = printJob.getPrinterId(); 263269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final boolean sameComponent = (componentName == null 264269403b032f965ff3847eb982c2f697229dc5a92Svetoslav || (printerId != null 265269403b032f965ff3847eb982c2f697229dc5a92Svetoslav && componentName.equals(printerId.getServiceName()))); 266269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final boolean sameAppId = appId == PrintManager.APP_ID_ANY 267269403b032f965ff3847eb982c2f697229dc5a92Svetoslav || printJob.getAppId() == appId; 268269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final boolean sameState = (state == printJob.getState()) 269269403b032f965ff3847eb982c2f697229dc5a92Svetoslav || (state == PrintJobInfo.STATE_ANY) 270269403b032f965ff3847eb982c2f697229dc5a92Svetoslav || (state == PrintJobInfo.STATE_ANY_VISIBLE_TO_CLIENTS 271d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov && isStateVisibleToUser(printJob.getState())) 272d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov || (state == PrintJobInfo.STATE_ANY_ACTIVE 2739b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov && isActiveState(printJob.getState())) 2749b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov || (state == PrintJobInfo.STATE_ANY_SCHEDULED 2759b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov && isScheduledState(printJob.getState())); 276269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (sameComponent && sameAppId && sameState) { 277269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (foundPrintJobs == null) { 278a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav foundPrintJobs = new ArrayList<>(); 279269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 280269403b032f965ff3847eb982c2f697229dc5a92Svetoslav foundPrintJobs.add(printJob); 281269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 282269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 283269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 284269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return foundPrintJobs; 285269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 286269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 287d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov private boolean isStateVisibleToUser(int state) { 288d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov return (isActiveState(state) && (state == PrintJobInfo.STATE_FAILED 2892fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav || state == PrintJobInfo.STATE_COMPLETED || state == PrintJobInfo.STATE_CANCELED 2902fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav || state == PrintJobInfo.STATE_BLOCKED)); 291d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov } 292d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov 2932fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId) { 294269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 295269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int printJobCount = mPrintJobs.size(); 296269403b032f965ff3847eb982c2f697229dc5a92Svetoslav for (int i = 0; i < printJobCount; i++) { 297269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = mPrintJobs.get(i); 2982fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav if (printJob.getId().equals(printJobId) 299269403b032f965ff3847eb982c2f697229dc5a92Svetoslav && (appId == PrintManager.APP_ID_ANY 300269403b032f965ff3847eb982c2f697229dc5a92Svetoslav || appId == printJob.getAppId())) { 301269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return printJob; 302269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 303269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 304269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return null; 305269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 306269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 307269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 3082fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public void createPrintJob(PrintJobInfo printJob) { 309269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 310269403b032f965ff3847eb982c2f697229dc5a92Svetoslav addPrintJobLocked(printJob); 311dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov setPrintJobState(printJob.getId(), PrintJobInfo.STATE_CREATED, null); 3127bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 3137bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav Message message = mHandlerCaller.obtainMessageO( 3147bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED, 3157bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav printJob); 3167bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav mHandlerCaller.executeOrSendMessage(message); 317269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 318269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 319269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 320269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void handleReadPrintJobsLocked() { 321dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov // Make a map with the files for a print job since we may have 322dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov // to delete some. One example of getting orphan files if the 323dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov // spooler crashes while constructing a print job. We do not 324dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov // persist partially populated print jobs under construction to 325dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov // avoid special handling for various attributes missing. 326dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov ArrayMap<PrintJobId, File> fileForJobMap = null; 327dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov File[] files = getFilesDir().listFiles(); 328dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov if (files != null) { 329dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov final int fileCount = files.length; 330dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov for (int i = 0; i < fileCount; i++) { 331dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov File file = files[i]; 332dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov if (file.isFile() && file.getName().startsWith(PRINT_JOB_FILE_PREFIX)) { 333dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov if (fileForJobMap == null) { 334dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov fileForJobMap = new ArrayMap<PrintJobId, File>(); 335dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 3362b40c83ae1ec17ea9371c3fd3ac6c79c156faa1dSvetoslav Ganov String printJobIdString = file.getName().substring( 3372b40c83ae1ec17ea9371c3fd3ac6c79c156faa1dSvetoslav Ganov PRINT_JOB_FILE_PREFIX.length(), 3382b40c83ae1ec17ea9371c3fd3ac6c79c156faa1dSvetoslav Ganov file.getName().indexOf('.')); 339dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov PrintJobId printJobId = PrintJobId.unflattenFromString( 340dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov printJobIdString); 341dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov fileForJobMap.put(printJobId, file); 342dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 343dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 344dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 345dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 346269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int printJobCount = mPrintJobs.size(); 347269403b032f965ff3847eb982c2f697229dc5a92Svetoslav for (int i = 0; i < printJobCount; i++) { 348269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = mPrintJobs.get(i); 349269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 350dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov // We want to have only the orphan files at the end. 351dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov if (fileForJobMap != null) { 352dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov fileForJobMap.remove(printJob.getId()); 353dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 354dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 355269403b032f965ff3847eb982c2f697229dc5a92Svetoslav switch (printJob.getState()) { 356269403b032f965ff3847eb982c2f697229dc5a92Svetoslav case PrintJobInfo.STATE_QUEUED: 357d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov case PrintJobInfo.STATE_STARTED: 358d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov case PrintJobInfo.STATE_BLOCKED: { 359d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov // We have a print job that was queued or started or blocked in 360d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov // the past but the device battery died or a crash occurred. In 361d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov // this case we assume the print job failed and let the user 362d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov // decide whether to restart the job or just cancel it. 363269403b032f965ff3847eb982c2f697229dc5a92Svetoslav setPrintJobState(printJob.getId(), PrintJobInfo.STATE_FAILED, 364269403b032f965ff3847eb982c2f697229dc5a92Svetoslav getString(R.string.no_connection_to_printer)); 3652fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } break; 366269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 367269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 368dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 369a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov if (!mPrintJobs.isEmpty()) { 370a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov // Update the notification. 371a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov mNotificationController.onUpdateNotifications(mPrintJobs); 372a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } 373a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov 374dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov // Delete the orphan files. 375dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov if (fileForJobMap != null) { 376dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov final int orphanFileCount = fileForJobMap.size(); 377dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov for (int i = 0; i < orphanFileCount; i++) { 378dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov File file = fileForJobMap.valueAt(i); 379dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov file.delete(); 380dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 381dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 382269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 383269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 384269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public void checkAllPrintJobsHandled() { 385269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 386269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (!hasActivePrintJobsLocked()) { 387269403b032f965ff3847eb982c2f697229dc5a92Svetoslav notifyOnAllPrintJobsHandled(); 388269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 389269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 390269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 391269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 3922fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public void writePrintJobData(final ParcelFileDescriptor fd, final PrintJobId printJobId) { 393269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final PrintJobInfo printJob; 394269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 395269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); 396269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 397269403b032f965ff3847eb982c2f697229dc5a92Svetoslav new AsyncTask<Void, Void, Void>() { 398269403b032f965ff3847eb982c2f697229dc5a92Svetoslav @Override 399269403b032f965ff3847eb982c2f697229dc5a92Svetoslav protected Void doInBackground(Void... params) { 400269403b032f965ff3847eb982c2f697229dc5a92Svetoslav FileInputStream in = null; 401269403b032f965ff3847eb982c2f697229dc5a92Svetoslav FileOutputStream out = null; 402269403b032f965ff3847eb982c2f697229dc5a92Svetoslav try { 403269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printJob != null) { 404a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav File file = generateFileForPrintJob(PrintSpoolerService.this, printJobId); 405269403b032f965ff3847eb982c2f697229dc5a92Svetoslav in = new FileInputStream(file); 406269403b032f965ff3847eb982c2f697229dc5a92Svetoslav out = new FileOutputStream(fd.getFileDescriptor()); 407269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 408269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final byte[] buffer = new byte[8192]; 409269403b032f965ff3847eb982c2f697229dc5a92Svetoslav while (true) { 410269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int readByteCount = in.read(buffer); 411269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (readByteCount < 0) { 412269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return null; 413269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 414269403b032f965ff3847eb982c2f697229dc5a92Svetoslav out.write(buffer, 0, readByteCount); 415269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 416269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (FileNotFoundException fnfe) { 417269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.e(LOG_TAG, "Error writing print job data!", fnfe); 418269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (IOException ioe) { 419269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.e(LOG_TAG, "Error writing print job data!", ioe); 420269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } finally { 421269403b032f965ff3847eb982c2f697229dc5a92Svetoslav IoUtils.closeQuietly(in); 422269403b032f965ff3847eb982c2f697229dc5a92Svetoslav IoUtils.closeQuietly(out); 423269403b032f965ff3847eb982c2f697229dc5a92Svetoslav IoUtils.closeQuietly(fd); 424269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 425269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.i(LOG_TAG, "[END WRITE]"); 426269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return null; 427269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 428269403b032f965ff3847eb982c2f697229dc5a92Svetoslav }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null); 429269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 430269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 431a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public static File generateFileForPrintJob(Context context, PrintJobId printJobId) { 432a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return new File(context.getFilesDir(), PRINT_JOB_FILE_PREFIX 4332fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav + printJobId.flattenToString() + "." + PRINT_FILE_EXTENSION); 434269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 435269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 436269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void addPrintJobLocked(PrintJobInfo printJob) { 437269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mPrintJobs.add(printJob); 438269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (DEBUG_PRINT_JOB_LIFECYCLE) { 439269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.i(LOG_TAG, "[ADD] " + printJob); 440269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 441269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 442269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 4432fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav private void removeObsoletePrintJobs() { 4442fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav synchronized (mLock) { 445885810de69d75979df4299d21fa236490767eae4Svetoslav boolean persistState = false; 4462fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav final int printJobCount = mPrintJobs.size(); 4472fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav for (int i = printJobCount - 1; i >= 0; i--) { 4482fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav PrintJobInfo printJob = mPrintJobs.get(i); 4492fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav if (isObsoleteState(printJob.getState())) { 4502fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav mPrintJobs.remove(i); 4512fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav if (DEBUG_PRINT_JOB_LIFECYCLE) { 4522fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav Slog.i(LOG_TAG, "[REMOVE] " + printJob.getId().flattenToString()); 4532fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 4542fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav removePrintJobFileLocked(printJob.getId()); 455885810de69d75979df4299d21fa236490767eae4Svetoslav persistState = true; 4562fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 4572fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 458885810de69d75979df4299d21fa236490767eae4Svetoslav if (persistState) { 459885810de69d75979df4299d21fa236490767eae4Svetoslav mPersistanceManager.writeStateLocked(); 460885810de69d75979df4299d21fa236490767eae4Svetoslav } 4612fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 4622fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 4632fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav 4642fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav private void removePrintJobFileLocked(PrintJobId printJobId) { 465a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav File file = generateFileForPrintJob(PrintSpoolerService.this, printJobId); 4662fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav if (file.exists()) { 4672fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav file.delete(); 468269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (DEBUG_PRINT_JOB_LIFECYCLE) { 469dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov Slog.i(LOG_TAG, "[REMOVE FILE FOR] " + printJobId); 470269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 471269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 472269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 473269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 4742fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public boolean setPrintJobState(PrintJobId printJobId, int state, String error) { 475269403b032f965ff3847eb982c2f697229dc5a92Svetoslav boolean success = false; 476269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 477269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 478269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); 479269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printJob != null) { 480704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov final int oldState = printJob.getState(); 481704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (oldState == state) { 482704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov return false; 483704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 484704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 485269403b032f965ff3847eb982c2f697229dc5a92Svetoslav success = true; 486269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 487269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setState(state); 488d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov printJob.setStateReason(error); 489a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov printJob.setCancelling(false); 490269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 491269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (DEBUG_PRINT_JOB_LIFECYCLE) { 492269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.i(LOG_TAG, "[STATE CHANGED] " + printJob); 493269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 494269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 495269403b032f965ff3847eb982c2f697229dc5a92Svetoslav switch (state) { 496269403b032f965ff3847eb982c2f697229dc5a92Svetoslav case PrintJobInfo.STATE_COMPLETED: 497269403b032f965ff3847eb982c2f697229dc5a92Svetoslav case PrintJobInfo.STATE_CANCELED: 498dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov mPrintJobs.remove(printJob); 4992fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav removePrintJobFileLocked(printJob.getId()); 500269403b032f965ff3847eb982c2f697229dc5a92Svetoslav // $fall-through$ 501269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 502269403b032f965ff3847eb982c2f697229dc5a92Svetoslav case PrintJobInfo.STATE_FAILED: { 503269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrinterId printerId = printJob.getPrinterId(); 504269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printerId != null) { 505269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ComponentName service = printerId.getServiceName(); 506269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (!hasActivePrintJobsForServiceLocked(service)) { 507269403b032f965ff3847eb982c2f697229dc5a92Svetoslav sendOnAllPrintJobsForServiceHandled(service); 508269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 509269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 510269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } break; 511269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 512269403b032f965ff3847eb982c2f697229dc5a92Svetoslav case PrintJobInfo.STATE_QUEUED: { 513269403b032f965ff3847eb982c2f697229dc5a92Svetoslav sendOnPrintJobQueued(new PrintJobInfo(printJob)); 514269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } break; 515269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 516269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 517269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (shouldPersistPrintJob(printJob)) { 518269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mPersistanceManager.writeStateLocked(); 519269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 520269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 521269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (!hasActivePrintJobsLocked()) { 522269403b032f965ff3847eb982c2f697229dc5a92Svetoslav notifyOnAllPrintJobsHandled(); 523269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 524704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 525dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov Message message = mHandlerCaller.obtainMessageO( 526704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED, 527dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov printJob); 528704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov mHandlerCaller.executeOrSendMessage(message); 529a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov 530a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov mNotificationController.onUpdateNotifications(mPrintJobs); 531269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 532269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 533269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 534269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return success; 535269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 536269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 537269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public boolean hasActivePrintJobsLocked() { 538269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int printJobCount = mPrintJobs.size(); 539269403b032f965ff3847eb982c2f697229dc5a92Svetoslav for (int i = 0; i < printJobCount; i++) { 540269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = mPrintJobs.get(i); 541269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (isActiveState(printJob.getState())) { 542269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return true; 543269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 544269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 545269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 546269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 547269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 548269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public boolean hasActivePrintJobsForServiceLocked(ComponentName service) { 549269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int printJobCount = mPrintJobs.size(); 550269403b032f965ff3847eb982c2f697229dc5a92Svetoslav for (int i = 0; i < printJobCount; i++) { 551269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = mPrintJobs.get(i); 55275d28505c8f73a977cc7ae0cc08a60120f7c92b2Svetoslav if (isActiveState(printJob.getState()) && printJob.getPrinterId() != null 553269403b032f965ff3847eb982c2f697229dc5a92Svetoslav && printJob.getPrinterId().getServiceName().equals(service)) { 554269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return true; 555269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 556269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 557269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 558269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 559269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 5602fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav private boolean isObsoleteState(int printJobState) { 561a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return (isTerminalState(printJobState) 5622fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav || printJobState == PrintJobInfo.STATE_QUEUED); 5632fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 5642fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav 5659b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov private boolean isScheduledState(int printJobState) { 5669b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov return printJobState == PrintJobInfo.STATE_QUEUED 5679b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov || printJobState == PrintJobInfo.STATE_STARTED 5689b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov || printJobState == PrintJobInfo.STATE_BLOCKED; 5699b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov } 5709b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov 571269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private boolean isActiveState(int printJobState) { 572269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return printJobState == PrintJobInfo.STATE_CREATED 573269403b032f965ff3847eb982c2f697229dc5a92Svetoslav || printJobState == PrintJobInfo.STATE_QUEUED 574d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov || printJobState == PrintJobInfo.STATE_STARTED 575d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov || printJobState == PrintJobInfo.STATE_BLOCKED; 576269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 577269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 578a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private boolean isTerminalState(int printJobState) { 5792fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav return printJobState == PrintJobInfo.STATE_COMPLETED 5802fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav || printJobState == PrintJobInfo.STATE_CANCELED; 5812fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 5822fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav 5832fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public boolean setPrintJobTag(PrintJobId printJobId, String tag) { 584269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 585269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); 586269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printJob != null) { 587269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String printJobTag = printJob.getTag(); 588269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printJobTag == null) { 589269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (tag == null) { 590269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 591269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 592269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } else if (printJobTag.equals(tag)) { 593269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 594269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 595269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setTag(tag); 596269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (shouldPersistPrintJob(printJob)) { 597269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mPersistanceManager.writeStateLocked(); 598269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 599269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return true; 600269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 601269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 602269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 603269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 604269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 605a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov public void setPrintJobCancelling(PrintJobId printJobId, boolean cancelling) { 606a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov synchronized (mLock) { 607a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); 608a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov if (printJob != null) { 609a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov printJob.setCancelling(cancelling); 610a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov if (shouldPersistPrintJob(printJob)) { 611a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov mPersistanceManager.writeStateLocked(); 612a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } 613a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov mNotificationController.onUpdateNotifications(mPrintJobs); 614a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov 615a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov Message message = mHandlerCaller.obtainMessageO( 616a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED, 617a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov printJob); 618a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov mHandlerCaller.executeOrSendMessage(message); 619a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } 620a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } 621a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } 622a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov 623a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public void updatePrintJobUserConfigurableOptionsNoPersistence(PrintJobInfo printJob) { 624269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 625a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav final int printJobCount = mPrintJobs.size(); 626a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav for (int i = 0; i < printJobCount; i++) { 627a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav PrintJobInfo cachedPrintJob = mPrintJobs.get(i); 628a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (cachedPrintJob.getId().equals(printJob.getId())) { 629a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav cachedPrintJob.setPrinterId(printJob.getPrinterId()); 630a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav cachedPrintJob.setPrinterName(printJob.getPrinterName()); 631a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav cachedPrintJob.setCopies(printJob.getCopies()); 632a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav cachedPrintJob.setDocumentInfo(printJob.getDocumentInfo()); 633a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav cachedPrintJob.setPages(printJob.getPages()); 634a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav cachedPrintJob.setAttributes(printJob.getAttributes()); 635a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav cachedPrintJob.setAdvancedOptions(printJob.getAdvancedOptions()); 636a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return; 637a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 638269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 639a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav throw new IllegalArgumentException("No print job with id:" + printJob.getId()); 640269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 641269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 642269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 643269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private boolean shouldPersistPrintJob(PrintJobInfo printJob) { 644269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return printJob.getState() >= PrintJobInfo.STATE_QUEUED; 645269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 646269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 647269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void notifyOnAllPrintJobsHandled() { 648269403b032f965ff3847eb982c2f697229dc5a92Svetoslav // This has to run on the tread that is persisting the current state 649269403b032f965ff3847eb982c2f697229dc5a92Svetoslav // since this call may result in the system unbinding from the spooler 650269403b032f965ff3847eb982c2f697229dc5a92Svetoslav // and as a result the spooler process may get killed before the write 651269403b032f965ff3847eb982c2f697229dc5a92Svetoslav // completes. 652269403b032f965ff3847eb982c2f697229dc5a92Svetoslav new AsyncTask<Void, Void, Void>() { 653269403b032f965ff3847eb982c2f697229dc5a92Svetoslav @Override 654269403b032f965ff3847eb982c2f697229dc5a92Svetoslav protected Void doInBackground(Void... params) { 655269403b032f965ff3847eb982c2f697229dc5a92Svetoslav sendOnAllPrintJobsHandled(); 656269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return null; 657269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 658269403b032f965ff3847eb982c2f697229dc5a92Svetoslav }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null); 659269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 660269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 661269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private final class PersistenceManager { 662269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String PERSIST_FILE_NAME = "print_spooler_state.xml"; 663269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 664269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_SPOOLER = "spooler"; 665269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_JOB = "job"; 666269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 667269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_PRINTER_ID = "printerId"; 668269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_PAGE_RANGE = "pageRange"; 669269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_ATTRIBUTES = "attributes"; 670269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_DOCUMENT_INFO = "documentInfo"; 671269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 672269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_ID = "id"; 673269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_LABEL = "label"; 674773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav private static final String ATTR_LABEL_RES_ID = "labelResId"; 675773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav private static final String ATTR_PACKAGE_NAME = "packageName"; 676269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_STATE = "state"; 677269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_APP_ID = "appId"; 678269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_TAG = "tag"; 679704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov private static final String ATTR_CREATION_TIME = "creationTime"; 680269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_COPIES = "copies"; 681704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov private static final String ATTR_PRINTER_NAME = "printerName"; 682704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov private static final String ATTR_STATE_REASON = "stateReason"; 683a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov private static final String ATTR_CANCELLING = "cancelling"; 684269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 685b4fda134761c9521a7e127db3806a07a18763b77Svetoslav private static final String TAG_ADVANCED_OPTIONS = "advancedOptions"; 686b4fda134761c9521a7e127db3806a07a18763b77Svetoslav private static final String TAG_ADVANCED_OPTION = "advancedOption"; 687b4fda134761c9521a7e127db3806a07a18763b77Svetoslav private static final String ATTR_KEY = "key"; 688b4fda134761c9521a7e127db3806a07a18763b77Svetoslav private static final String ATTR_TYPE = "type"; 689b4fda134761c9521a7e127db3806a07a18763b77Svetoslav private static final String ATTR_VALUE = "value"; 690b4fda134761c9521a7e127db3806a07a18763b77Svetoslav private static final String TYPE_STRING = "string"; 691b4fda134761c9521a7e127db3806a07a18763b77Svetoslav private static final String TYPE_INT = "int"; 692b4fda134761c9521a7e127db3806a07a18763b77Svetoslav 693269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_MEDIA_SIZE = "mediaSize"; 694269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_RESOLUTION = "resolution"; 695269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_MARGINS = "margins"; 696269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 697269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_COLOR_MODE = "colorMode"; 698269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 699704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov private static final String ATTR_LOCAL_ID = "localId"; 700269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_SERVICE_NAME = "serviceName"; 701269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 702269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_WIDTH_MILS = "widthMils"; 703269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_HEIGHT_MILS = "heightMils"; 704269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 705269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_HORIZONTAL_DPI = "horizontalDip"; 706269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_VERTICAL_DPI = "verticalDpi"; 707269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 708269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_LEFT_MILS = "leftMils"; 709269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_TOP_MILS = "topMils"; 710269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_RIGHT_MILS = "rightMils"; 711269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_BOTTOM_MILS = "bottomMils"; 712269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 713269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_START = "start"; 714269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_END = "end"; 715269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 716269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_NAME = "name"; 717269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_PAGE_COUNT = "pageCount"; 718269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_CONTENT_TYPE = "contentType"; 7197d7888d1c7daa78ee0ad24a24c8dd54b01749259Svetoslav Ganov private static final String ATTR_DATA_SIZE = "dataSize"; 720269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 721269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private final AtomicFile mStatePersistFile; 722269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 723269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private boolean mWriteStateScheduled; 724269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 725269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private PersistenceManager() { 726269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mStatePersistFile = new AtomicFile(new File(getFilesDir(), 727269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PERSIST_FILE_NAME)); 728269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 729269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 730269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public void writeStateLocked() { 7314237c92d850b7fb0fa0be15df94e4d1689e353fcSvet Ganov if (!PERSISTENCE_MANAGER_ENABLED) { 732269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return; 733269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 734269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (mWriteStateScheduled) { 735269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return; 736269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 737269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mWriteStateScheduled = true; 738269403b032f965ff3847eb982c2f697229dc5a92Svetoslav new AsyncTask<Void, Void, Void>() { 739269403b032f965ff3847eb982c2f697229dc5a92Svetoslav @Override 740269403b032f965ff3847eb982c2f697229dc5a92Svetoslav protected Void doInBackground(Void... params) { 741269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 742269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mWriteStateScheduled = false; 743269403b032f965ff3847eb982c2f697229dc5a92Svetoslav doWriteStateLocked(); 744269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 745269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return null; 746269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 747269403b032f965ff3847eb982c2f697229dc5a92Svetoslav }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null); 748269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 749269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 750269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void doWriteStateLocked() { 751269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (DEBUG_PERSISTENCE) { 752269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.i(LOG_TAG, "[PERSIST START]"); 753269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 754269403b032f965ff3847eb982c2f697229dc5a92Svetoslav FileOutputStream out = null; 755269403b032f965ff3847eb982c2f697229dc5a92Svetoslav try { 756269403b032f965ff3847eb982c2f697229dc5a92Svetoslav out = mStatePersistFile.startWrite(); 757269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 758269403b032f965ff3847eb982c2f697229dc5a92Svetoslav XmlSerializer serializer = new FastXmlSerializer(); 759269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.setOutput(out, "utf-8"); 760269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startDocument(null, true); 761269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_SPOOLER); 762269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 763269403b032f965ff3847eb982c2f697229dc5a92Svetoslav List<PrintJobInfo> printJobs = mPrintJobs; 764269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 765269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int printJobCount = printJobs.size(); 766269403b032f965ff3847eb982c2f697229dc5a92Svetoslav for (int j = 0; j < printJobCount; j++) { 767269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = printJobs.get(j); 768269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 769885810de69d75979df4299d21fa236490767eae4Svetoslav if (!shouldPersistPrintJob(printJob)) { 770885810de69d75979df4299d21fa236490767eae4Svetoslav continue; 771885810de69d75979df4299d21fa236490767eae4Svetoslav } 772885810de69d75979df4299d21fa236490767eae4Svetoslav 773269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_JOB); 774269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 7752fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav serializer.attribute(null, ATTR_ID, printJob.getId().flattenToString()); 776269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_LABEL, printJob.getLabel().toString()); 777269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_STATE, String.valueOf(printJob.getState())); 778269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_APP_ID, String.valueOf(printJob.getAppId())); 779269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String tag = printJob.getTag(); 780269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (tag != null) { 781269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_TAG, tag); 782269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 783704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov serializer.attribute(null, ATTR_CREATION_TIME, String.valueOf( 784704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov printJob.getCreationTime())); 785269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_COPIES, String.valueOf(printJob.getCopies())); 786704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov String printerName = printJob.getPrinterName(); 787704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (!TextUtils.isEmpty(printerName)) { 788704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov serializer.attribute(null, ATTR_PRINTER_NAME, printerName); 789704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 790704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov String stateReason = printJob.getStateReason(); 791704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (!TextUtils.isEmpty(stateReason)) { 792704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov serializer.attribute(null, ATTR_STATE_REASON, stateReason); 793704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 794a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov serializer.attribute(null, ATTR_CANCELLING, String.valueOf( 795a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov printJob.isCancelling())); 796269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 797269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrinterId printerId = printJob.getPrinterId(); 798269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printerId != null) { 799269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_PRINTER_ID); 800269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_LOCAL_ID, printerId.getLocalId()); 801269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_SERVICE_NAME, printerId.getServiceName() 802269403b032f965ff3847eb982c2f697229dc5a92Svetoslav .flattenToString()); 803269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_PRINTER_ID); 804269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 805269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 806269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PageRange[] pages = printJob.getPages(); 807269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (pages != null) { 808269403b032f965ff3847eb982c2f697229dc5a92Svetoslav for (int i = 0; i < pages.length; i++) { 809269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_PAGE_RANGE); 810269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_START, String.valueOf( 811269403b032f965ff3847eb982c2f697229dc5a92Svetoslav pages[i].getStart())); 812269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_END, String.valueOf( 813269403b032f965ff3847eb982c2f697229dc5a92Svetoslav pages[i].getEnd())); 814269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_PAGE_RANGE); 815269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 816269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 817269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 818269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintAttributes attributes = printJob.getAttributes(); 819269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (attributes != null) { 820269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_ATTRIBUTES); 821269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 822269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int colorMode = attributes.getColorMode(); 823269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_COLOR_MODE, 824269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String.valueOf(colorMode)); 825269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 826269403b032f965ff3847eb982c2f697229dc5a92Svetoslav MediaSize mediaSize = attributes.getMediaSize(); 827269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (mediaSize != null) { 828269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_MEDIA_SIZE); 829269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_ID, mediaSize.getId()); 830269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_WIDTH_MILS, String.valueOf( 831269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mediaSize.getWidthMils())); 832269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_HEIGHT_MILS, String.valueOf( 833269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mediaSize.getHeightMils())); 834a76233ae845da4bc9e3bcd89821701a747215e7bSvetoslav // We prefer to store only the package name and 835a76233ae845da4bc9e3bcd89821701a747215e7bSvetoslav // resource id and fallback to the label. 836a76233ae845da4bc9e3bcd89821701a747215e7bSvetoslav if (!TextUtils.isEmpty(mediaSize.mPackageName) 837773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav && mediaSize.mLabelResId > 0) { 838773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav serializer.attribute(null, ATTR_PACKAGE_NAME, 839773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav mediaSize.mPackageName); 840773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav serializer.attribute(null, ATTR_LABEL_RES_ID, 841773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav String.valueOf(mediaSize.mLabelResId)); 842773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav } else { 843773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav serializer.attribute(null, ATTR_LABEL, 844773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav mediaSize.getLabel(getPackageManager())); 845773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav } 846269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_MEDIA_SIZE); 847269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 848269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 849269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Resolution resolution = attributes.getResolution(); 850269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (resolution != null) { 851269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_RESOLUTION); 852269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_ID, resolution.getId()); 853269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_HORIZONTAL_DPI, String.valueOf( 854269403b032f965ff3847eb982c2f697229dc5a92Svetoslav resolution.getHorizontalDpi())); 855269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_VERTICAL_DPI, String.valueOf( 856269403b032f965ff3847eb982c2f697229dc5a92Svetoslav resolution.getVerticalDpi())); 857c6066799ad130140159230d14451b429eb828755Svetoslav serializer.attribute(null, ATTR_LABEL, 858651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav resolution.getLabel()); 859269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_RESOLUTION); 860269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 861269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 862651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav Margins margins = attributes.getMinMargins(); 863269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (margins != null) { 864269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_MARGINS); 865269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_LEFT_MILS, String.valueOf( 866269403b032f965ff3847eb982c2f697229dc5a92Svetoslav margins.getLeftMils())); 867269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_TOP_MILS, String.valueOf( 868269403b032f965ff3847eb982c2f697229dc5a92Svetoslav margins.getTopMils())); 869269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_RIGHT_MILS, String.valueOf( 870269403b032f965ff3847eb982c2f697229dc5a92Svetoslav margins.getRightMils())); 871269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_BOTTOM_MILS, String.valueOf( 872269403b032f965ff3847eb982c2f697229dc5a92Svetoslav margins.getBottomMils())); 873269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_MARGINS); 874269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 875269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 876269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_ATTRIBUTES); 877269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 878269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 879269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintDocumentInfo documentInfo = printJob.getDocumentInfo(); 880269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (documentInfo != null) { 881269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_DOCUMENT_INFO); 882269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_NAME, documentInfo.getName()); 883269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_CONTENT_TYPE, String.valueOf( 884269403b032f965ff3847eb982c2f697229dc5a92Svetoslav documentInfo.getContentType())); 885269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_PAGE_COUNT, String.valueOf( 886269403b032f965ff3847eb982c2f697229dc5a92Svetoslav documentInfo.getPageCount())); 8877d7888d1c7daa78ee0ad24a24c8dd54b01749259Svetoslav Ganov serializer.attribute(null, ATTR_DATA_SIZE, String.valueOf( 8887d7888d1c7daa78ee0ad24a24c8dd54b01749259Svetoslav Ganov documentInfo.getDataSize())); 889269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_DOCUMENT_INFO); 890269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 891269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 892b4fda134761c9521a7e127db3806a07a18763b77Svetoslav Bundle advancedOptions = printJob.getAdvancedOptions(); 893b4fda134761c9521a7e127db3806a07a18763b77Svetoslav if (advancedOptions != null) { 894b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.startTag(null, TAG_ADVANCED_OPTIONS); 895b4fda134761c9521a7e127db3806a07a18763b77Svetoslav for (String key : advancedOptions.keySet()) { 896b4fda134761c9521a7e127db3806a07a18763b77Svetoslav Object value = advancedOptions.get(key); 897b4fda134761c9521a7e127db3806a07a18763b77Svetoslav if (value instanceof String) { 898b4fda134761c9521a7e127db3806a07a18763b77Svetoslav String stringValue = (String) value; 899b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.startTag(null, TAG_ADVANCED_OPTION); 900b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.attribute(null, ATTR_KEY, key); 901b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.attribute(null, ATTR_TYPE, TYPE_STRING); 902b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.attribute(null, ATTR_VALUE, stringValue); 903b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.endTag(null, TAG_ADVANCED_OPTION); 904b4fda134761c9521a7e127db3806a07a18763b77Svetoslav } else if (value instanceof Integer) { 905b4fda134761c9521a7e127db3806a07a18763b77Svetoslav String intValue = Integer.toString((Integer) value); 906b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.startTag(null, TAG_ADVANCED_OPTION); 907b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.attribute(null, ATTR_KEY, key); 908b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.attribute(null, ATTR_TYPE, TYPE_INT); 909b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.attribute(null, ATTR_VALUE, intValue); 910b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.endTag(null, TAG_ADVANCED_OPTION); 911b4fda134761c9521a7e127db3806a07a18763b77Svetoslav } 912b4fda134761c9521a7e127db3806a07a18763b77Svetoslav } 913b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.endTag(null, TAG_ADVANCED_OPTIONS); 914b4fda134761c9521a7e127db3806a07a18763b77Svetoslav } 915b4fda134761c9521a7e127db3806a07a18763b77Svetoslav 916269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_JOB); 917269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 918269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (DEBUG_PERSISTENCE) { 919269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.i(LOG_TAG, "[PERSISTED] " + printJob); 920269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 921269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 922269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 923269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_SPOOLER); 924269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endDocument(); 925269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mStatePersistFile.finishWrite(out); 926269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (DEBUG_PERSISTENCE) { 927269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.i(LOG_TAG, "[PERSIST END]"); 928269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 929269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (IOException e) { 930269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.w(LOG_TAG, "Failed to write state, restoring backup.", e); 931269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mStatePersistFile.failWrite(out); 932269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } finally { 933269403b032f965ff3847eb982c2f697229dc5a92Svetoslav IoUtils.closeQuietly(out); 934269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 935269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 936269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 937269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public void readStateLocked() { 9384237c92d850b7fb0fa0be15df94e4d1689e353fcSvet Ganov if (!PERSISTENCE_MANAGER_ENABLED) { 939269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return; 940269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 941269403b032f965ff3847eb982c2f697229dc5a92Svetoslav FileInputStream in = null; 942269403b032f965ff3847eb982c2f697229dc5a92Svetoslav try { 943269403b032f965ff3847eb982c2f697229dc5a92Svetoslav in = mStatePersistFile.openRead(); 944269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (FileNotFoundException e) { 945269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.i(LOG_TAG, "No existing print spooler state."); 946269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return; 947269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 948269403b032f965ff3847eb982c2f697229dc5a92Svetoslav try { 949269403b032f965ff3847eb982c2f697229dc5a92Svetoslav XmlPullParser parser = Xml.newPullParser(); 950269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.setInput(in, null); 951269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parseState(parser); 952269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (IllegalStateException ise) { 953269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.w(LOG_TAG, "Failed parsing ", ise); 954269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (NullPointerException npe) { 955269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.w(LOG_TAG, "Failed parsing ", npe); 956269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (NumberFormatException nfe) { 957269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.w(LOG_TAG, "Failed parsing ", nfe); 958269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (XmlPullParserException xppe) { 959269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.w(LOG_TAG, "Failed parsing ", xppe); 960269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (IOException ioe) { 961269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.w(LOG_TAG, "Failed parsing ", ioe); 962269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (IndexOutOfBoundsException iobe) { 963269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.w(LOG_TAG, "Failed parsing ", iobe); 964269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } finally { 965269403b032f965ff3847eb982c2f697229dc5a92Svetoslav IoUtils.closeQuietly(in); 966269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 967269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 968269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 969269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void parseState(XmlPullParser parser) 970269403b032f965ff3847eb982c2f697229dc5a92Svetoslav throws IOException, XmlPullParserException { 971269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 972269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 973269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.START_TAG, TAG_SPOOLER); 974269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 975269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 976269403b032f965ff3847eb982c2f697229dc5a92Svetoslav while (parsePrintJob(parser)) { 977269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 978269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 979269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 980269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 981269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_SPOOLER); 982269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 983269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 984269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private boolean parsePrintJob(XmlPullParser parser) 985269403b032f965ff3847eb982c2f697229dc5a92Svetoslav throws IOException, XmlPullParserException { 986269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 987269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (!accept(parser, XmlPullParser.START_TAG, TAG_JOB)) { 988269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 989269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 990269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 991269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = new PrintJobInfo(); 992269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 9932fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav PrintJobId printJobId = PrintJobId.unflattenFromString( 9942fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav parser.getAttributeValue(null, ATTR_ID)); 995269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setId(printJobId); 996269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String label = parser.getAttributeValue(null, ATTR_LABEL); 997269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setLabel(label); 998269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int state = Integer.parseInt(parser.getAttributeValue(null, ATTR_STATE)); 999269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setState(state); 1000269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int appId = Integer.parseInt(parser.getAttributeValue(null, ATTR_APP_ID)); 1001269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setAppId(appId); 1002269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String tag = parser.getAttributeValue(null, ATTR_TAG); 1003269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setTag(tag); 1004704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov String creationTime = parser.getAttributeValue(null, ATTR_CREATION_TIME); 1005704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov printJob.setCreationTime(Long.parseLong(creationTime)); 1006269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String copies = parser.getAttributeValue(null, ATTR_COPIES); 1007269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setCopies(Integer.parseInt(copies)); 1008704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov String printerName = parser.getAttributeValue(null, ATTR_PRINTER_NAME); 1009704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov printJob.setPrinterName(printerName); 1010704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov String stateReason = parser.getAttributeValue(null, ATTR_STATE_REASON); 1011704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov printJob.setStateReason(stateReason); 1012a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov String cancelling = parser.getAttributeValue(null, ATTR_CANCELLING); 1013a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov printJob.setCancelling(!TextUtils.isEmpty(cancelling) 1014a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov ? Boolean.parseBoolean(cancelling) : false); 1015269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1016269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1017269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1018269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1019269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (accept(parser, XmlPullParser.START_TAG, TAG_PRINTER_ID)) { 1020269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String localId = parser.getAttributeValue(null, ATTR_LOCAL_ID); 1021269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ComponentName service = ComponentName.unflattenFromString(parser.getAttributeValue( 1022269403b032f965ff3847eb982c2f697229dc5a92Svetoslav null, ATTR_SERVICE_NAME)); 1023269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setPrinterId(new PrinterId(service, localId)); 1024269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1025269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1026269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_PRINTER_ID); 1027269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1028269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1029269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1030269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1031269403b032f965ff3847eb982c2f697229dc5a92Svetoslav List<PageRange> pageRanges = null; 1032269403b032f965ff3847eb982c2f697229dc5a92Svetoslav while (accept(parser, XmlPullParser.START_TAG, TAG_PAGE_RANGE)) { 1033269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int start = Integer.parseInt(parser.getAttributeValue(null, ATTR_START)); 1034269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int end = Integer.parseInt(parser.getAttributeValue(null, ATTR_END)); 1035269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PageRange pageRange = new PageRange(start, end); 1036269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (pageRanges == null) { 1037269403b032f965ff3847eb982c2f697229dc5a92Svetoslav pageRanges = new ArrayList<PageRange>(); 1038269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1039269403b032f965ff3847eb982c2f697229dc5a92Svetoslav pageRanges.add(pageRange); 1040269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1041269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1042269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_PAGE_RANGE); 1043269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1044b4fda134761c9521a7e127db3806a07a18763b77Svetoslav skipEmptyTextTags(parser); 1045269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1046269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (pageRanges != null) { 1047269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PageRange[] pageRangesArray = new PageRange[pageRanges.size()]; 1048269403b032f965ff3847eb982c2f697229dc5a92Svetoslav pageRanges.toArray(pageRangesArray); 1049269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setPages(pageRangesArray); 1050269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1051269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1052269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1053269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (accept(parser, XmlPullParser.START_TAG, TAG_ATTRIBUTES)) { 1054269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1055269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintAttributes.Builder builder = new PrintAttributes.Builder(); 1056269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1057269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String colorMode = parser.getAttributeValue(null, ATTR_COLOR_MODE); 1058269403b032f965ff3847eb982c2f697229dc5a92Svetoslav builder.setColorMode(Integer.parseInt(colorMode)); 1059269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1060269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1061269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1062269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1063269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (accept(parser, XmlPullParser.START_TAG, TAG_MEDIA_SIZE)) { 1064269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String id = parser.getAttributeValue(null, ATTR_ID); 1065269403b032f965ff3847eb982c2f697229dc5a92Svetoslav label = parser.getAttributeValue(null, ATTR_LABEL); 1066269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int widthMils = Integer.parseInt(parser.getAttributeValue(null, 1067269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_WIDTH_MILS)); 1068269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int heightMils = Integer.parseInt(parser.getAttributeValue(null, 1069269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_HEIGHT_MILS)); 1070773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav String packageName = parser.getAttributeValue(null, ATTR_PACKAGE_NAME); 1071b206f1271d17164c3f2f65219eee7a0b4b4fa6dcSvetoslav String labelResIdString = parser.getAttributeValue(null, ATTR_LABEL_RES_ID); 1072b206f1271d17164c3f2f65219eee7a0b4b4fa6dcSvetoslav final int labelResId = (labelResIdString != null) 1073b206f1271d17164c3f2f65219eee7a0b4b4fa6dcSvetoslav ? Integer.parseInt(labelResIdString) : 0; 1074773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav label = parser.getAttributeValue(null, ATTR_LABEL); 1075b4fda134761c9521a7e127db3806a07a18763b77Svetoslav MediaSize mediaSize = new MediaSize(id, label, packageName, 1076b4fda134761c9521a7e127db3806a07a18763b77Svetoslav widthMils, heightMils, labelResId); 1077269403b032f965ff3847eb982c2f697229dc5a92Svetoslav builder.setMediaSize(mediaSize); 1078269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1079269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1080269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_MEDIA_SIZE); 1081269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1082269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1083269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1084269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1085269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (accept(parser, XmlPullParser.START_TAG, TAG_RESOLUTION)) { 1086269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String id = parser.getAttributeValue(null, ATTR_ID); 1087269403b032f965ff3847eb982c2f697229dc5a92Svetoslav label = parser.getAttributeValue(null, ATTR_LABEL); 1088269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int horizontalDpi = Integer.parseInt(parser.getAttributeValue(null, 1089269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_HORIZONTAL_DPI)); 1090269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int verticalDpi = Integer.parseInt(parser.getAttributeValue(null, 1091269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_VERTICAL_DPI)); 1092c6066799ad130140159230d14451b429eb828755Svetoslav Resolution resolution = new Resolution(id, label, horizontalDpi, verticalDpi); 1093269403b032f965ff3847eb982c2f697229dc5a92Svetoslav builder.setResolution(resolution); 1094269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1095269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1096269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_RESOLUTION); 1097269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1098269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1099269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1100269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1101269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (accept(parser, XmlPullParser.START_TAG, TAG_MARGINS)) { 1102269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int leftMils = Integer.parseInt(parser.getAttributeValue(null, 1103269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_LEFT_MILS)); 1104269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int topMils = Integer.parseInt(parser.getAttributeValue(null, 1105269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_TOP_MILS)); 1106269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int rightMils = Integer.parseInt(parser.getAttributeValue(null, 1107269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_RIGHT_MILS)); 1108269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int bottomMils = Integer.parseInt(parser.getAttributeValue(null, 1109269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_BOTTOM_MILS)); 1110269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Margins margins = new Margins(leftMils, topMils, rightMils, bottomMils); 1111651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav builder.setMinMargins(margins); 1112269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1113269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1114269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_MARGINS); 1115269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1116269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1117269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1118651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav printJob.setAttributes(builder.build()); 1119269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1120269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1121269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_ATTRIBUTES); 1122269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1123269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1124269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1125269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1126269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (accept(parser, XmlPullParser.START_TAG, TAG_DOCUMENT_INFO)) { 1127269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String name = parser.getAttributeValue(null, ATTR_NAME); 1128269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int pageCount = Integer.parseInt(parser.getAttributeValue(null, 1129269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_PAGE_COUNT)); 1130269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int contentType = Integer.parseInt(parser.getAttributeValue(null, 1131269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_CONTENT_TYPE)); 11327d7888d1c7daa78ee0ad24a24c8dd54b01749259Svetoslav Ganov final int dataSize = Integer.parseInt(parser.getAttributeValue(null, 11337d7888d1c7daa78ee0ad24a24c8dd54b01749259Svetoslav Ganov ATTR_DATA_SIZE)); 1134269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintDocumentInfo info = new PrintDocumentInfo.Builder(name) 1135269403b032f965ff3847eb982c2f697229dc5a92Svetoslav .setPageCount(pageCount) 1136651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav .setContentType(contentType).build(); 1137269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setDocumentInfo(info); 11387d7888d1c7daa78ee0ad24a24c8dd54b01749259Svetoslav Ganov info.setDataSize(dataSize); 1139269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1140269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1141269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_DOCUMENT_INFO); 1142269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1143269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1144269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1145b4fda134761c9521a7e127db3806a07a18763b77Svetoslav skipEmptyTextTags(parser); 1146b4fda134761c9521a7e127db3806a07a18763b77Svetoslav if (accept(parser, XmlPullParser.START_TAG, TAG_ADVANCED_OPTIONS)) { 1147b4fda134761c9521a7e127db3806a07a18763b77Svetoslav parser.next(); 1148b4fda134761c9521a7e127db3806a07a18763b77Svetoslav skipEmptyTextTags(parser); 1149b4fda134761c9521a7e127db3806a07a18763b77Svetoslav Bundle advancedOptions = new Bundle(); 1150b4fda134761c9521a7e127db3806a07a18763b77Svetoslav while (accept(parser, XmlPullParser.START_TAG, TAG_ADVANCED_OPTION)) { 1151b4fda134761c9521a7e127db3806a07a18763b77Svetoslav String key = parser.getAttributeValue(null, ATTR_KEY); 1152b4fda134761c9521a7e127db3806a07a18763b77Svetoslav String value = parser.getAttributeValue(null, ATTR_VALUE); 1153b4fda134761c9521a7e127db3806a07a18763b77Svetoslav String type = parser.getAttributeValue(null, ATTR_TYPE); 1154b4fda134761c9521a7e127db3806a07a18763b77Svetoslav if (TYPE_STRING.equals(type)) { 1155b4fda134761c9521a7e127db3806a07a18763b77Svetoslav advancedOptions.putString(key, value); 1156b4fda134761c9521a7e127db3806a07a18763b77Svetoslav } else if (TYPE_INT.equals(type)) { 1157b4fda134761c9521a7e127db3806a07a18763b77Svetoslav advancedOptions.putInt(key, Integer.valueOf(value)); 1158b4fda134761c9521a7e127db3806a07a18763b77Svetoslav } 1159b4fda134761c9521a7e127db3806a07a18763b77Svetoslav parser.next(); 1160b4fda134761c9521a7e127db3806a07a18763b77Svetoslav skipEmptyTextTags(parser); 1161b4fda134761c9521a7e127db3806a07a18763b77Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_ADVANCED_OPTION); 1162b4fda134761c9521a7e127db3806a07a18763b77Svetoslav parser.next(); 1163b4fda134761c9521a7e127db3806a07a18763b77Svetoslav skipEmptyTextTags(parser); 1164b4fda134761c9521a7e127db3806a07a18763b77Svetoslav } 1165b4fda134761c9521a7e127db3806a07a18763b77Svetoslav printJob.setAdvancedOptions(advancedOptions); 1166b4fda134761c9521a7e127db3806a07a18763b77Svetoslav skipEmptyTextTags(parser); 1167b4fda134761c9521a7e127db3806a07a18763b77Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_ADVANCED_OPTIONS); 1168b4fda134761c9521a7e127db3806a07a18763b77Svetoslav parser.next(); 1169b4fda134761c9521a7e127db3806a07a18763b77Svetoslav } 1170b4fda134761c9521a7e127db3806a07a18763b77Svetoslav 1171269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mPrintJobs.add(printJob); 1172269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1173269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (DEBUG_PERSISTENCE) { 1174269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.i(LOG_TAG, "[RESTORED] " + printJob); 1175269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1176269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1177269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1178269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_JOB); 1179269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1180269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return true; 1181269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1182269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1183269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void expect(XmlPullParser parser, int type, String tag) 1184269403b032f965ff3847eb982c2f697229dc5a92Svetoslav throws IOException, XmlPullParserException { 1185269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (!accept(parser, type, tag)) { 1186269403b032f965ff3847eb982c2f697229dc5a92Svetoslav throw new XmlPullParserException("Exepected event: " + type 1187269403b032f965ff3847eb982c2f697229dc5a92Svetoslav + " and tag: " + tag + " but got event: " + parser.getEventType() 1188269403b032f965ff3847eb982c2f697229dc5a92Svetoslav + " and tag:" + parser.getName()); 1189269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1190269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1191269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1192269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void skipEmptyTextTags(XmlPullParser parser) 1193269403b032f965ff3847eb982c2f697229dc5a92Svetoslav throws IOException, XmlPullParserException { 1194269403b032f965ff3847eb982c2f697229dc5a92Svetoslav while (accept(parser, XmlPullParser.TEXT, null) 1195269403b032f965ff3847eb982c2f697229dc5a92Svetoslav && "\n".equals(parser.getText())) { 1196269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1197269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1198269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1199269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1200269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private boolean accept(XmlPullParser parser, int type, String tag) 1201269403b032f965ff3847eb982c2f697229dc5a92Svetoslav throws IOException, XmlPullParserException { 1202269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (parser.getEventType() != type) { 1203269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 1204269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1205269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (tag != null) { 1206269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (!tag.equals(parser.getName())) { 1207269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 1208269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1209269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } else if (parser.getName() != null) { 1210269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 1211269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1212269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return true; 1213269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1214269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 12157bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 1216a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public final class PrintSpooler extends IPrintSpooler.Stub { 12177bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 12187bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void getPrintJobInfos(IPrintSpoolerCallbacks callback, 12197bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav ComponentName componentName, int state, int appId, int sequence) 12207bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav throws RemoteException { 12217bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav List<PrintJobInfo> printJobs = null; 12227bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav try { 12237bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav printJobs = PrintSpoolerService.this.getPrintJobInfos( 12247bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav componentName, state, appId); 12257bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } finally { 12267bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav callback.onGetPrintJobInfosResult(printJobs, sequence); 12277bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12287bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12297bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 12307bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 12317bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void getPrintJobInfo(PrintJobId printJobId, IPrintSpoolerCallbacks callback, 12327bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav int appId, int sequence) throws RemoteException { 12337bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav PrintJobInfo printJob = null; 12347bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav try { 12357bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav printJob = PrintSpoolerService.this.getPrintJobInfo(printJobId, appId); 12367bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } finally { 12377bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav callback.onGetPrintJobInfoResult(printJob, sequence); 12387bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12397bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12407bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 12417bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 12427bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void createPrintJob(PrintJobInfo printJob) { 12437bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav PrintSpoolerService.this.createPrintJob(printJob); 12447bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12457bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 12467bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 12477bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void setPrintJobState(PrintJobId printJobId, int state, String error, 12487bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav IPrintSpoolerCallbacks callback, int sequece) throws RemoteException { 12497bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav boolean success = false; 12507bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav try { 12517bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav success = PrintSpoolerService.this.setPrintJobState( 12527bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav printJobId, state, error); 12537bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } finally { 12547bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav callback.onSetPrintJobStateResult(success, sequece); 12557bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12567bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12577bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 12587bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 12597bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void setPrintJobTag(PrintJobId printJobId, String tag, 12607bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav IPrintSpoolerCallbacks callback, int sequece) throws RemoteException { 12617bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav boolean success = false; 12627bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav try { 12637bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav success = PrintSpoolerService.this.setPrintJobTag(printJobId, tag); 12647bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } finally { 12657bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav callback.onSetPrintJobTagResult(success, sequece); 12667bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12677bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12687bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 12697bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 12707bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void writePrintJobData(ParcelFileDescriptor fd, PrintJobId printJobId) { 12717bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav PrintSpoolerService.this.writePrintJobData(fd, printJobId); 12727bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12737bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 12747bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 12757bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void setClient(IPrintSpoolerClient client) { 12767bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav Message message = mHandlerCaller.obtainMessageO( 12777bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav HandlerCallerCallback.MSG_SET_CLIENT, client); 12787bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav mHandlerCaller.executeOrSendMessage(message); 12797bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12807bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 12817bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 12827bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void removeObsoletePrintJobs() { 12837bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav PrintSpoolerService.this.removeObsoletePrintJobs(); 12847bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12857bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 12867bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 12877bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 12887bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav PrintSpoolerService.this.dump(fd, writer, args); 12897bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12907bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 12917bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 12927bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void setPrintJobCancelling(PrintJobId printJobId, boolean cancelling) { 12937bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav PrintSpoolerService.this.setPrintJobCancelling(printJobId, cancelling); 12947bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12957bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 12967bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public PrintSpoolerService getService() { 12977bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav return PrintSpoolerService.this; 12987bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 12997bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 13004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov} 1301