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 19b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmannimport android.annotation.FloatRange; 20b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmannimport android.annotation.NonNull; 21b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmannimport android.annotation.Nullable; 22d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmannimport android.annotation.StringRes; 234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.app.Service; 244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.ComponentName; 25a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.content.Context; 264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.Intent; 27bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmannimport android.graphics.drawable.Icon; 28269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.os.AsyncTask; 29b4fda134761c9521a7e127db3806a07a18763b77Svetoslavimport android.os.Bundle; 304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.IBinder; 314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Message; 324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.ParcelFileDescriptor; 334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.RemoteException; 34a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.IPrintSpooler; 35a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.IPrintSpoolerCallbacks; 36835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganovimport android.print.IPrintSpoolerClient; 37269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PageRange; 384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.PrintAttributes; 39269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrintAttributes.Margins; 40269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrintAttributes.MediaSize; 41269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrintAttributes.Resolution; 42269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrintDocumentInfo; 432fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslavimport android.print.PrintJobId; 444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.PrintJobInfo; 45269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrintManager; 46269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.print.PrinterId; 47a76233ae845da4bc9e3bcd89821701a747215e7bSvetoslavimport android.text.TextUtils; 48dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganovimport android.util.ArrayMap; 49269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.util.AtomicFile; 50835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganovimport android.util.Log; 514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.util.Slog; 52269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport android.util.Xml; 534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 54dcc34fd8a3f718e5e5cfaccb87eeffd64ac80f63Chris Wrenimport com.android.internal.logging.MetricsLogger; 55269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport com.android.internal.os.HandlerCaller; 56269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport com.android.internal.util.FastXmlSerializer; 57a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport com.android.printspooler.R; 58853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmannimport com.android.printspooler.util.ApprovedPrintServices; 594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 602fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslavimport libcore.io.IoUtils; 612fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav 62269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport org.xmlpull.v1.XmlPullParser; 63269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport org.xmlpull.v1.XmlPullParserException; 64269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport org.xmlpull.v1.XmlSerializer; 65269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 66269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.io.File; 67dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganovimport java.io.FileDescriptor; 68269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.io.FileInputStream; 69269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.io.FileNotFoundException; 70269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.io.FileOutputStream; 71269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.io.IOException; 72dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganovimport java.io.PrintWriter; 739e9e2e73c6ec7bece20268196dc89ad0c8bafad4Wojciech Staszkiewiczimport java.nio.charset.StandardCharsets; 74269403b032f965ff3847eb982c2f697229dc5a92Svetoslavimport java.util.ArrayList; 75835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganovimport java.util.List; 76853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmannimport java.util.Set; 77835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov 784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/** 794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Service for exposing some of the {@link PrintSpooler} functionality to 804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * another process. 814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovpublic final class PrintSpoolerService extends Service { 834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 84269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String LOG_TAG = "PrintSpoolerService"; 85269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 86b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav private static final boolean DEBUG_PRINT_JOB_LIFECYCLE = false; 87269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 88c6066799ad130140159230d14451b429eb828755Svetoslav private static final boolean DEBUG_PERSISTENCE = false; 89269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 904237c92d850b7fb0fa0be15df94e4d1689e353fcSvet Ganov private static final boolean PERSISTENCE_MANAGER_ENABLED = true; 91269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 922e3012624b703a653fed44d4dc1b8904406c0d99Philip P. Moltmann private static final String PRINT_JOB_STATE_HISTO = "print_job_state"; 932e3012624b703a653fed44d4dc1b8904406c0d99Philip P. Moltmann 94835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov private static final long CHECK_ALL_PRINTJOBS_HANDLED_DELAY = 5000; 95835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov 96dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov private static final String PRINT_JOB_FILE_PREFIX = "print_job_"; 97dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 98269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String PRINT_FILE_EXTENSION = "pdf"; 99269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 100269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final Object sLock = new Object(); 101269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 102269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private final Object mLock = new Object(); 103269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 104a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private final List<PrintJobInfo> mPrintJobs = new ArrayList<>(); 105269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 106269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static PrintSpoolerService sInstance; 107269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 108835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov private IPrintSpoolerClient mClient; 1094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 110269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private HandlerCaller mHandlerCaller; 111269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 112269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private PersistenceManager mPersistanceManager; 113269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 114269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private NotificationController mNotificationController; 115269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 116bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann /** Cache for custom printer icons loaded from the print service */ 117bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann private CustomPrinterIconCache mCustomIconCache; 118bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann 119269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public static PrintSpoolerService peekInstance() { 120269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (sLock) { 121269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return sInstance; 122269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 123269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 1264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void onCreate() { 1274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov super.onCreate(); 128269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mHandlerCaller = new HandlerCaller(this, getMainLooper(), 129269403b032f965ff3847eb982c2f697229dc5a92Svetoslav new HandlerCallerCallback(), false); 130269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 131269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mPersistanceManager = new PersistenceManager(); 132269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mNotificationController = new NotificationController(PrintSpoolerService.this); 133bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann mCustomIconCache = new CustomPrinterIconCache(getCacheDir()); 134269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 135269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 136269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mPersistanceManager.readStateLocked(); 137269403b032f965ff3847eb982c2f697229dc5a92Svetoslav handleReadPrintJobsLocked(); 138269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 139269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 140269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (sLock) { 141269403b032f965ff3847eb982c2f697229dc5a92Svetoslav sInstance = this; 142269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 146bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann public void onDestroy() { 147bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann super.onDestroy(); 148bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann } 149bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann 150bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann @Override 1514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public IBinder onBind(Intent intent) { 1527bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav return new PrintSpooler(); 1534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 155dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov @Override 156dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 157853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann String prefix = (args.length > 0) ? args[0] : ""; 158853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann String tab = " "; 159dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 160853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann synchronized (mLock) { 161dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov pw.append(prefix).append("print jobs:").println(); 162dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov final int printJobCount = mPrintJobs.size(); 163dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov for (int i = 0; i < printJobCount; i++) { 164dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov PrintJobInfo printJob = mPrintJobs.get(i); 165dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov pw.append(prefix).append(tab).append(printJob.toString()); 166dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov pw.println(); 167dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 168dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 169dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov pw.append(prefix).append("print job files:").println(); 170dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov File[] files = getFilesDir().listFiles(); 171dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov if (files != null) { 172dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov final int fileCount = files.length; 173dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov for (int i = 0; i < fileCount; i++) { 174dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov File file = files[i]; 175dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov if (file.isFile() && file.getName().startsWith(PRINT_JOB_FILE_PREFIX)) { 176dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov pw.append(prefix).append(tab).append(file.getName()).println(); 177dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 178dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 179dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 180dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 181853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann 182853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann pw.append(prefix).append("approved print services:").println(); 183853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann Set<String> approvedPrintServices = (new ApprovedPrintServices(this)).getApprovedServices(); 184853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann if (approvedPrintServices != null) { 185853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann for (String approvedService : approvedPrintServices) { 186853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann pw.append(prefix).append(tab).append(approvedService).println(); 187853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann } 188853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann } 189dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 190dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 191269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void sendOnPrintJobQueued(PrintJobInfo printJob) { 192269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Message message = mHandlerCaller.obtainMessageO( 193269403b032f965ff3847eb982c2f697229dc5a92Svetoslav HandlerCallerCallback.MSG_ON_PRINT_JOB_QUEUED, printJob); 194269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mHandlerCaller.executeOrSendMessage(message); 195269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 196269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 197269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void sendOnAllPrintJobsForServiceHandled(ComponentName service) { 198269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Message message = mHandlerCaller.obtainMessageO( 199269403b032f965ff3847eb982c2f697229dc5a92Svetoslav HandlerCallerCallback.MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED, service); 200269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mHandlerCaller.executeOrSendMessage(message); 201269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 202269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 203269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void sendOnAllPrintJobsHandled() { 204269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Message message = mHandlerCaller.obtainMessage( 205269403b032f965ff3847eb982c2f697229dc5a92Svetoslav HandlerCallerCallback.MSG_ON_ALL_PRINT_JOBS_HANDLED); 206269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mHandlerCaller.executeOrSendMessage(message); 207269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 208269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 209269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private final class HandlerCallerCallback implements HandlerCaller.Callback { 210704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov public static final int MSG_SET_CLIENT = 1; 2117bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final int MSG_ON_PRINT_JOB_QUEUED = 2; 2127bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final int MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED = 3; 2137bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 4; 2147bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final int MSG_CHECK_ALL_PRINTJOBS_HANDLED = 5; 2157bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final int MSG_ON_PRINT_JOB_STATE_CHANGED = 6; 2164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 218269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public void executeMessage(Message message) { 219835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov switch (message.what) { 220835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov case MSG_SET_CLIENT: { 221269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 222269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mClient = (IPrintSpoolerClient) message.obj; 223269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (mClient != null) { 224269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Message msg = mHandlerCaller.obtainMessage( 225269403b032f965ff3847eb982c2f697229dc5a92Svetoslav HandlerCallerCallback.MSG_CHECK_ALL_PRINTJOBS_HANDLED); 226269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mHandlerCaller.sendMessageDelayed(msg, 227269403b032f965ff3847eb982c2f697229dc5a92Svetoslav CHECK_ALL_PRINTJOBS_HANDLED_DELAY); 228269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 229835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 230835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } break; 231835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov 232835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov case MSG_ON_PRINT_JOB_QUEUED: { 233835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov PrintJobInfo printJob = (PrintJobInfo) message.obj; 234835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov if (mClient != null) { 235835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov try { 236835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov mClient.onPrintJobQueued(printJob); 237835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } catch (RemoteException re) { 238835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov Slog.e(LOG_TAG, "Error notify for a queued print job.", re); 239835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 240835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 241835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } break; 242835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov 243835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov case MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED: { 244835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov ComponentName service = (ComponentName) message.obj; 245835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov if (mClient != null) { 246835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov try { 247835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov mClient.onAllPrintJobsForServiceHandled(service); 248835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } catch (RemoteException re) { 249835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov Slog.e(LOG_TAG, "Error notify for all print jobs per service" 250835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov + " handled.", re); 251835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 252835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 253835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } break; 254835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov 255835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov case MSG_ON_ALL_PRINT_JOBS_HANDLED: { 256835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov if (mClient != null) { 257835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov try { 258835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov mClient.onAllPrintJobsHandled(); 259835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } catch (RemoteException re) { 260835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov Slog.e(LOG_TAG, "Error notify for all print job handled.", re); 261835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 262835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 263835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } break; 264835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov 265835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov case MSG_CHECK_ALL_PRINTJOBS_HANDLED: { 266269403b032f965ff3847eb982c2f697229dc5a92Svetoslav checkAllPrintJobsHandled(); 267269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } break; 268704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 269704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov case MSG_ON_PRINT_JOB_STATE_CHANGED: { 270704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (mClient != null) { 271dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov PrintJobInfo printJob = (PrintJobInfo) message.obj; 272704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov try { 273dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov mClient.onPrintJobStateChanged(printJob); 274704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } catch (RemoteException re) { 275704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov Slog.e(LOG_TAG, "Error notify for print job state change.", re); 276704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 277704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 278704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } break; 2794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 282269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 283269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public List<PrintJobInfo> getPrintJobInfos(ComponentName componentName, 284269403b032f965ff3847eb982c2f697229dc5a92Svetoslav int state, int appId) { 285269403b032f965ff3847eb982c2f697229dc5a92Svetoslav List<PrintJobInfo> foundPrintJobs = null; 286269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 287269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int printJobCount = mPrintJobs.size(); 288269403b032f965ff3847eb982c2f697229dc5a92Svetoslav for (int i = 0; i < printJobCount; i++) { 289269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = mPrintJobs.get(i); 290269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrinterId printerId = printJob.getPrinterId(); 291269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final boolean sameComponent = (componentName == null 292269403b032f965ff3847eb982c2f697229dc5a92Svetoslav || (printerId != null 293269403b032f965ff3847eb982c2f697229dc5a92Svetoslav && componentName.equals(printerId.getServiceName()))); 294269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final boolean sameAppId = appId == PrintManager.APP_ID_ANY 295269403b032f965ff3847eb982c2f697229dc5a92Svetoslav || printJob.getAppId() == appId; 296269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final boolean sameState = (state == printJob.getState()) 297269403b032f965ff3847eb982c2f697229dc5a92Svetoslav || (state == PrintJobInfo.STATE_ANY) 298269403b032f965ff3847eb982c2f697229dc5a92Svetoslav || (state == PrintJobInfo.STATE_ANY_VISIBLE_TO_CLIENTS 299d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov && isStateVisibleToUser(printJob.getState())) 300d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov || (state == PrintJobInfo.STATE_ANY_ACTIVE 3019b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov && isActiveState(printJob.getState())) 3029b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov || (state == PrintJobInfo.STATE_ANY_SCHEDULED 3039b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov && isScheduledState(printJob.getState())); 304269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (sameComponent && sameAppId && sameState) { 305269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (foundPrintJobs == null) { 306a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav foundPrintJobs = new ArrayList<>(); 307269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 308269403b032f965ff3847eb982c2f697229dc5a92Svetoslav foundPrintJobs.add(printJob); 309269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 310269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 311269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 312269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return foundPrintJobs; 313269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 314269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 315d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov private boolean isStateVisibleToUser(int state) { 316d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov return (isActiveState(state) && (state == PrintJobInfo.STATE_FAILED 3172fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav || state == PrintJobInfo.STATE_COMPLETED || state == PrintJobInfo.STATE_CANCELED 3182fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav || state == PrintJobInfo.STATE_BLOCKED)); 319d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov } 320d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov 3212fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId) { 322269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 323269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int printJobCount = mPrintJobs.size(); 324269403b032f965ff3847eb982c2f697229dc5a92Svetoslav for (int i = 0; i < printJobCount; i++) { 325269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = mPrintJobs.get(i); 3262fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav if (printJob.getId().equals(printJobId) 327269403b032f965ff3847eb982c2f697229dc5a92Svetoslav && (appId == PrintManager.APP_ID_ANY 328269403b032f965ff3847eb982c2f697229dc5a92Svetoslav || appId == printJob.getAppId())) { 329269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return printJob; 330269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 331269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 332269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return null; 333269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 334269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 335269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 3362fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public void createPrintJob(PrintJobInfo printJob) { 337269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 338269403b032f965ff3847eb982c2f697229dc5a92Svetoslav addPrintJobLocked(printJob); 339dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov setPrintJobState(printJob.getId(), PrintJobInfo.STATE_CREATED, null); 3407bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 3417bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav Message message = mHandlerCaller.obtainMessageO( 3427bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED, 3437bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav printJob); 3447bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav mHandlerCaller.executeOrSendMessage(message); 345269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 346269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 347269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 348269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void handleReadPrintJobsLocked() { 349dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov // Make a map with the files for a print job since we may have 350dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov // to delete some. One example of getting orphan files if the 351dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov // spooler crashes while constructing a print job. We do not 352dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov // persist partially populated print jobs under construction to 353dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov // avoid special handling for various attributes missing. 354dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov ArrayMap<PrintJobId, File> fileForJobMap = null; 355dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov File[] files = getFilesDir().listFiles(); 356dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov if (files != null) { 357dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov final int fileCount = files.length; 358dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov for (int i = 0; i < fileCount; i++) { 359dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov File file = files[i]; 360dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov if (file.isFile() && file.getName().startsWith(PRINT_JOB_FILE_PREFIX)) { 361dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov if (fileForJobMap == null) { 362dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov fileForJobMap = new ArrayMap<PrintJobId, File>(); 363dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 3642b40c83ae1ec17ea9371c3fd3ac6c79c156faa1dSvetoslav Ganov String printJobIdString = file.getName().substring( 3652b40c83ae1ec17ea9371c3fd3ac6c79c156faa1dSvetoslav Ganov PRINT_JOB_FILE_PREFIX.length(), 3662b40c83ae1ec17ea9371c3fd3ac6c79c156faa1dSvetoslav Ganov file.getName().indexOf('.')); 367dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov PrintJobId printJobId = PrintJobId.unflattenFromString( 368dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov printJobIdString); 369dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov fileForJobMap.put(printJobId, file); 370dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 371dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 372dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 373dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 374269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int printJobCount = mPrintJobs.size(); 375269403b032f965ff3847eb982c2f697229dc5a92Svetoslav for (int i = 0; i < printJobCount; i++) { 376269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = mPrintJobs.get(i); 377269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 378dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov // We want to have only the orphan files at the end. 379dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov if (fileForJobMap != null) { 380dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov fileForJobMap.remove(printJob.getId()); 381dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 382dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 383269403b032f965ff3847eb982c2f697229dc5a92Svetoslav switch (printJob.getState()) { 384269403b032f965ff3847eb982c2f697229dc5a92Svetoslav case PrintJobInfo.STATE_QUEUED: 385d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov case PrintJobInfo.STATE_STARTED: 386d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov case PrintJobInfo.STATE_BLOCKED: { 387d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov // We have a print job that was queued or started or blocked in 388d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov // the past but the device battery died or a crash occurred. In 389d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov // this case we assume the print job failed and let the user 390d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov // decide whether to restart the job or just cancel it. 391269403b032f965ff3847eb982c2f697229dc5a92Svetoslav setPrintJobState(printJob.getId(), PrintJobInfo.STATE_FAILED, 392269403b032f965ff3847eb982c2f697229dc5a92Svetoslav getString(R.string.no_connection_to_printer)); 3932fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } break; 394269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 395269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 396dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 397a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov if (!mPrintJobs.isEmpty()) { 398a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov // Update the notification. 399a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov mNotificationController.onUpdateNotifications(mPrintJobs); 400a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } 401a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov 402dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov // Delete the orphan files. 403dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov if (fileForJobMap != null) { 404dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov final int orphanFileCount = fileForJobMap.size(); 405dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov for (int i = 0; i < orphanFileCount; i++) { 406dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov File file = fileForJobMap.valueAt(i); 407dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov file.delete(); 408dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 409dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } 410269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 411269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 412269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public void checkAllPrintJobsHandled() { 413269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 414269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (!hasActivePrintJobsLocked()) { 415269403b032f965ff3847eb982c2f697229dc5a92Svetoslav notifyOnAllPrintJobsHandled(); 416269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 417269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 418269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 419269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 4202fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public void writePrintJobData(final ParcelFileDescriptor fd, final PrintJobId printJobId) { 421269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final PrintJobInfo printJob; 422269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 423269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); 424269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 425269403b032f965ff3847eb982c2f697229dc5a92Svetoslav new AsyncTask<Void, Void, Void>() { 426269403b032f965ff3847eb982c2f697229dc5a92Svetoslav @Override 427269403b032f965ff3847eb982c2f697229dc5a92Svetoslav protected Void doInBackground(Void... params) { 428269403b032f965ff3847eb982c2f697229dc5a92Svetoslav FileInputStream in = null; 429269403b032f965ff3847eb982c2f697229dc5a92Svetoslav FileOutputStream out = null; 430269403b032f965ff3847eb982c2f697229dc5a92Svetoslav try { 431269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printJob != null) { 432a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav File file = generateFileForPrintJob(PrintSpoolerService.this, printJobId); 433269403b032f965ff3847eb982c2f697229dc5a92Svetoslav in = new FileInputStream(file); 434269403b032f965ff3847eb982c2f697229dc5a92Svetoslav out = new FileOutputStream(fd.getFileDescriptor()); 435269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 436269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final byte[] buffer = new byte[8192]; 437269403b032f965ff3847eb982c2f697229dc5a92Svetoslav while (true) { 438269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int readByteCount = in.read(buffer); 439269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (readByteCount < 0) { 440269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return null; 441269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 442269403b032f965ff3847eb982c2f697229dc5a92Svetoslav out.write(buffer, 0, readByteCount); 443269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 444269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (FileNotFoundException fnfe) { 445269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.e(LOG_TAG, "Error writing print job data!", fnfe); 446269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (IOException ioe) { 447269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.e(LOG_TAG, "Error writing print job data!", ioe); 448269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } finally { 449269403b032f965ff3847eb982c2f697229dc5a92Svetoslav IoUtils.closeQuietly(in); 450269403b032f965ff3847eb982c2f697229dc5a92Svetoslav IoUtils.closeQuietly(out); 451269403b032f965ff3847eb982c2f697229dc5a92Svetoslav IoUtils.closeQuietly(fd); 452269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 453269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.i(LOG_TAG, "[END WRITE]"); 454269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return null; 455269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 456269403b032f965ff3847eb982c2f697229dc5a92Svetoslav }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null); 457269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 458269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 459a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public static File generateFileForPrintJob(Context context, PrintJobId printJobId) { 460a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return new File(context.getFilesDir(), PRINT_JOB_FILE_PREFIX 4612fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav + printJobId.flattenToString() + "." + PRINT_FILE_EXTENSION); 462269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 463269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 464269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void addPrintJobLocked(PrintJobInfo printJob) { 465269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mPrintJobs.add(printJob); 466269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (DEBUG_PRINT_JOB_LIFECYCLE) { 467269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.i(LOG_TAG, "[ADD] " + printJob); 468269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 469269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 470269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 4712fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav private void removeObsoletePrintJobs() { 4722fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav synchronized (mLock) { 473885810de69d75979df4299d21fa236490767eae4Svetoslav boolean persistState = false; 4742fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav final int printJobCount = mPrintJobs.size(); 4752fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav for (int i = printJobCount - 1; i >= 0; i--) { 4762fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav PrintJobInfo printJob = mPrintJobs.get(i); 4772fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav if (isObsoleteState(printJob.getState())) { 4782fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav mPrintJobs.remove(i); 4792fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav if (DEBUG_PRINT_JOB_LIFECYCLE) { 4802fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav Slog.i(LOG_TAG, "[REMOVE] " + printJob.getId().flattenToString()); 4812fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 4822fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav removePrintJobFileLocked(printJob.getId()); 483885810de69d75979df4299d21fa236490767eae4Svetoslav persistState = true; 4842fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 4852fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 486885810de69d75979df4299d21fa236490767eae4Svetoslav if (persistState) { 487885810de69d75979df4299d21fa236490767eae4Svetoslav mPersistanceManager.writeStateLocked(); 488885810de69d75979df4299d21fa236490767eae4Svetoslav } 4892fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 4902fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 4912fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav 4922fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav private void removePrintJobFileLocked(PrintJobId printJobId) { 493a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav File file = generateFileForPrintJob(PrintSpoolerService.this, printJobId); 4942fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav if (file.exists()) { 4952fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav file.delete(); 496269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (DEBUG_PRINT_JOB_LIFECYCLE) { 497dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov Slog.i(LOG_TAG, "[REMOVE FILE FOR] " + printJobId); 498269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 499269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 500269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 501269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 5024bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann /** 5034bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann * Notify all interested parties that a print job has been updated. 5044bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann * 5054bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann * @param printJob The updated print job. 5064bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann */ 5074bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann private void notifyPrintJobUpdated(PrintJobInfo printJob) { 5084bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann Message message = mHandlerCaller.obtainMessageO( 5094bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED, 5104bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann printJob); 5114bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann mHandlerCaller.executeOrSendMessage(message); 5124bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann 5134bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann mNotificationController.onUpdateNotifications(mPrintJobs); 5144bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann } 5154bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann 5162fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public boolean setPrintJobState(PrintJobId printJobId, int state, String error) { 517269403b032f965ff3847eb982c2f697229dc5a92Svetoslav boolean success = false; 518269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 519269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 520269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); 521269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printJob != null) { 522704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov final int oldState = printJob.getState(); 523704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (oldState == state) { 524704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov return false; 525704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 526704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 527269403b032f965ff3847eb982c2f697229dc5a92Svetoslav success = true; 528269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 529269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setState(state); 530b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann printJob.setStatus(error); 531a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov printJob.setCancelling(false); 532269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 533269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (DEBUG_PRINT_JOB_LIFECYCLE) { 534269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.i(LOG_TAG, "[STATE CHANGED] " + printJob); 535269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 536269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 5372e3012624b703a653fed44d4dc1b8904406c0d99Philip P. Moltmann MetricsLogger.histogram(this, PRINT_JOB_STATE_HISTO, state); 538269403b032f965ff3847eb982c2f697229dc5a92Svetoslav switch (state) { 539269403b032f965ff3847eb982c2f697229dc5a92Svetoslav case PrintJobInfo.STATE_COMPLETED: 540269403b032f965ff3847eb982c2f697229dc5a92Svetoslav case PrintJobInfo.STATE_CANCELED: 541dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov mPrintJobs.remove(printJob); 5422fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav removePrintJobFileLocked(printJob.getId()); 543269403b032f965ff3847eb982c2f697229dc5a92Svetoslav // $fall-through$ 544269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 545269403b032f965ff3847eb982c2f697229dc5a92Svetoslav case PrintJobInfo.STATE_FAILED: { 546269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrinterId printerId = printJob.getPrinterId(); 547269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printerId != null) { 548269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ComponentName service = printerId.getServiceName(); 549269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (!hasActivePrintJobsForServiceLocked(service)) { 550269403b032f965ff3847eb982c2f697229dc5a92Svetoslav sendOnAllPrintJobsForServiceHandled(service); 551269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 552269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 553269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } break; 554269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 555269403b032f965ff3847eb982c2f697229dc5a92Svetoslav case PrintJobInfo.STATE_QUEUED: { 556269403b032f965ff3847eb982c2f697229dc5a92Svetoslav sendOnPrintJobQueued(new PrintJobInfo(printJob)); 557269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } break; 558269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 559269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 560269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (shouldPersistPrintJob(printJob)) { 561269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mPersistanceManager.writeStateLocked(); 562269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 563269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 564269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (!hasActivePrintJobsLocked()) { 565269403b032f965ff3847eb982c2f697229dc5a92Svetoslav notifyOnAllPrintJobsHandled(); 566269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 567704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 5684bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann notifyPrintJobUpdated(printJob); 569269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 570269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 571269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 572269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return success; 573269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 574269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 575b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann /** 576b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann * Set the progress for a print job. 577b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann * 578b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann * @param printJobId ID of the print job to update 579b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann * @param progress the new progress 580b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann */ 581b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann public void setProgress(@NonNull PrintJobId printJobId, 582b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann @FloatRange(from=0.0, to=1.0) float progress) { 583b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann synchronized (mLock) { 584b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY).setProgress(progress); 585b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann 586b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann mNotificationController.onUpdateNotifications(mPrintJobs); 587b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann } 588b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann } 589b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann 590d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann /** 591d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann * Set the status for a print job. 592d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann * 593d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann * @param printJobId ID of the print job to update 594d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann * @param status the new status 595d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann */ 596d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann public void setStatus(@NonNull PrintJobId printJobId, @Nullable CharSequence status) { 597d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann synchronized (mLock) { 5984bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); 599d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann 6004bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann if (printJob != null) { 6014bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann printJob.setStatus(status); 6024bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann notifyPrintJobUpdated(printJob); 6034bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann } 604d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann } 605d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann } 606d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann 607d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann /** 608d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann * Set the status for a print job. 609d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann * 610d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann * @param printJobId ID of the print job to update 611d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann * @param status the new status as a string resource 612d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann * @param appPackageName app package the resource belongs to 613d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann */ 614d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann public void setStatus(@NonNull PrintJobId printJobId, @StringRes int status, 615d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann @Nullable CharSequence appPackageName) { 616d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann synchronized (mLock) { 6174bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); 618b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann 6194bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann if (printJob != null) { 6204bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann printJob.setStatus(status, appPackageName); 6214bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann notifyPrintJobUpdated(printJob); 6224bd8fac48ed28494ca24e456e20b3058f78e8fe9Philip P. Moltmann } 623d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann } 624d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann } 625b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann 626269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public boolean hasActivePrintJobsLocked() { 627269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int printJobCount = mPrintJobs.size(); 628269403b032f965ff3847eb982c2f697229dc5a92Svetoslav for (int i = 0; i < printJobCount; i++) { 629269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = mPrintJobs.get(i); 630269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (isActiveState(printJob.getState())) { 631269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return true; 632269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 633269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 634269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 635269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 636269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 637269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public boolean hasActivePrintJobsForServiceLocked(ComponentName service) { 638269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int printJobCount = mPrintJobs.size(); 639269403b032f965ff3847eb982c2f697229dc5a92Svetoslav for (int i = 0; i < printJobCount; i++) { 640269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = mPrintJobs.get(i); 64175d28505c8f73a977cc7ae0cc08a60120f7c92b2Svetoslav if (isActiveState(printJob.getState()) && printJob.getPrinterId() != null 642269403b032f965ff3847eb982c2f697229dc5a92Svetoslav && printJob.getPrinterId().getServiceName().equals(service)) { 643269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return true; 644269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 645269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 646269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 647269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 648269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 6492fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav private boolean isObsoleteState(int printJobState) { 650a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return (isTerminalState(printJobState) 6512fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav || printJobState == PrintJobInfo.STATE_QUEUED); 6522fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 6532fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav 6549b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov private boolean isScheduledState(int printJobState) { 6559b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov return printJobState == PrintJobInfo.STATE_QUEUED 6569b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov || printJobState == PrintJobInfo.STATE_STARTED 6579b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov || printJobState == PrintJobInfo.STATE_BLOCKED; 6589b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov } 6599b6d3a153f44010a75907c6a9742c89a57d4e5eeSvetoslav Ganov 660269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private boolean isActiveState(int printJobState) { 661269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return printJobState == PrintJobInfo.STATE_CREATED 662269403b032f965ff3847eb982c2f697229dc5a92Svetoslav || printJobState == PrintJobInfo.STATE_QUEUED 663d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov || printJobState == PrintJobInfo.STATE_STARTED 664d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov || printJobState == PrintJobInfo.STATE_BLOCKED; 665269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 666269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 667a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private boolean isTerminalState(int printJobState) { 6682fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav return printJobState == PrintJobInfo.STATE_COMPLETED 6692fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav || printJobState == PrintJobInfo.STATE_CANCELED; 6702fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 6712fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav 6722fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public boolean setPrintJobTag(PrintJobId printJobId, String tag) { 673269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 674269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); 675269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printJob != null) { 676269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String printJobTag = printJob.getTag(); 677269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printJobTag == null) { 678269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (tag == null) { 679269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 680269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 681269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } else if (printJobTag.equals(tag)) { 682269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 683269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 684269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setTag(tag); 685269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (shouldPersistPrintJob(printJob)) { 686269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mPersistanceManager.writeStateLocked(); 687269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 688269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return true; 689269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 690269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 691269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 692269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 693269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 694a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov public void setPrintJobCancelling(PrintJobId printJobId, boolean cancelling) { 695a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov synchronized (mLock) { 696a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); 697a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov if (printJob != null) { 698a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov printJob.setCancelling(cancelling); 699a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov if (shouldPersistPrintJob(printJob)) { 700a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov mPersistanceManager.writeStateLocked(); 701a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } 702a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov mNotificationController.onUpdateNotifications(mPrintJobs); 703a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov 704a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov Message message = mHandlerCaller.obtainMessageO( 705a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED, 706a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov printJob); 707a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov mHandlerCaller.executeOrSendMessage(message); 708a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } 709a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } 710a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } 711a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov 712a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public void updatePrintJobUserConfigurableOptionsNoPersistence(PrintJobInfo printJob) { 713269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 714a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav final int printJobCount = mPrintJobs.size(); 715a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav for (int i = 0; i < printJobCount; i++) { 716a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav PrintJobInfo cachedPrintJob = mPrintJobs.get(i); 717a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (cachedPrintJob.getId().equals(printJob.getId())) { 718a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav cachedPrintJob.setPrinterId(printJob.getPrinterId()); 719a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav cachedPrintJob.setPrinterName(printJob.getPrinterName()); 720a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav cachedPrintJob.setCopies(printJob.getCopies()); 721a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav cachedPrintJob.setDocumentInfo(printJob.getDocumentInfo()); 722a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav cachedPrintJob.setPages(printJob.getPages()); 723a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav cachedPrintJob.setAttributes(printJob.getAttributes()); 724a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav cachedPrintJob.setAdvancedOptions(printJob.getAdvancedOptions()); 725a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return; 726a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 727269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 728a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav throw new IllegalArgumentException("No print job with id:" + printJob.getId()); 729269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 730269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 731269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 732269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private boolean shouldPersistPrintJob(PrintJobInfo printJob) { 733269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return printJob.getState() >= PrintJobInfo.STATE_QUEUED; 734269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 735269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 736269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void notifyOnAllPrintJobsHandled() { 737269403b032f965ff3847eb982c2f697229dc5a92Svetoslav // This has to run on the tread that is persisting the current state 738269403b032f965ff3847eb982c2f697229dc5a92Svetoslav // since this call may result in the system unbinding from the spooler 739269403b032f965ff3847eb982c2f697229dc5a92Svetoslav // and as a result the spooler process may get killed before the write 740269403b032f965ff3847eb982c2f697229dc5a92Svetoslav // completes. 741269403b032f965ff3847eb982c2f697229dc5a92Svetoslav new AsyncTask<Void, Void, Void>() { 742269403b032f965ff3847eb982c2f697229dc5a92Svetoslav @Override 743269403b032f965ff3847eb982c2f697229dc5a92Svetoslav protected Void doInBackground(Void... params) { 744269403b032f965ff3847eb982c2f697229dc5a92Svetoslav sendOnAllPrintJobsHandled(); 745269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return null; 746269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 747269403b032f965ff3847eb982c2f697229dc5a92Svetoslav }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null); 748269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 749269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 750bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann /** 751bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann * Handle that a custom icon for a printer was loaded. 752bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann * 753bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann * @param printerId the id of the printer the icon belongs to 754bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann * @param icon the icon that was loaded 755bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann * @see android.print.PrinterInfo.Builder#setHasCustomPrinterIcon() 756bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann */ 757bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann public void onCustomPrinterIconLoaded(PrinterId printerId, Icon icon) { 758bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann mCustomIconCache.onCustomPrinterIconLoaded(printerId, icon); 759bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann } 760bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann 761bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann /** 762bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann * Get the custom icon for a printer. If the icon is not cached, the icon is 763bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann * requested asynchronously. Once it is available the printer is updated. 764bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann * 765bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann * @param printerId the id of the printer the icon should be loaded for 766bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann * @return the custom icon to be used for the printer or null if the icon is 767bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann * not yet available 768bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann * @see android.print.PrinterInfo.Builder#setHasCustomPrinterIcon() 769bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann */ 770bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann public Icon getCustomPrinterIcon(PrinterId printerId) { 771bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann return mCustomIconCache.getIcon(printerId); 772bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann } 773bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann 774bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann /** 775bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann * Clear the custom printer icon cache. 776bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann */ 777bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann public void clearCustomPrinterIconCache() { 778bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann mCustomIconCache.clear(); 779bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann } 780bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann 781269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private final class PersistenceManager { 782269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String PERSIST_FILE_NAME = "print_spooler_state.xml"; 783269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 784269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_SPOOLER = "spooler"; 785269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_JOB = "job"; 786269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 787269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_PRINTER_ID = "printerId"; 788269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_PAGE_RANGE = "pageRange"; 789269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_ATTRIBUTES = "attributes"; 790269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_DOCUMENT_INFO = "documentInfo"; 791269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 792269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_ID = "id"; 793269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_LABEL = "label"; 794773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav private static final String ATTR_LABEL_RES_ID = "labelResId"; 795773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav private static final String ATTR_PACKAGE_NAME = "packageName"; 796269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_STATE = "state"; 797269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_APP_ID = "appId"; 798269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_TAG = "tag"; 799704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov private static final String ATTR_CREATION_TIME = "creationTime"; 800269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_COPIES = "copies"; 801704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov private static final String ATTR_PRINTER_NAME = "printerName"; 802704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov private static final String ATTR_STATE_REASON = "stateReason"; 803b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann private static final String ATTR_STATUS = "status"; 804b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann private static final String ATTR_PROGRESS = "progress"; 805a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov private static final String ATTR_CANCELLING = "cancelling"; 806269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 807b4fda134761c9521a7e127db3806a07a18763b77Svetoslav private static final String TAG_ADVANCED_OPTIONS = "advancedOptions"; 808b4fda134761c9521a7e127db3806a07a18763b77Svetoslav private static final String TAG_ADVANCED_OPTION = "advancedOption"; 809b4fda134761c9521a7e127db3806a07a18763b77Svetoslav private static final String ATTR_KEY = "key"; 810b4fda134761c9521a7e127db3806a07a18763b77Svetoslav private static final String ATTR_TYPE = "type"; 811b4fda134761c9521a7e127db3806a07a18763b77Svetoslav private static final String ATTR_VALUE = "value"; 812b4fda134761c9521a7e127db3806a07a18763b77Svetoslav private static final String TYPE_STRING = "string"; 813b4fda134761c9521a7e127db3806a07a18763b77Svetoslav private static final String TYPE_INT = "int"; 814b4fda134761c9521a7e127db3806a07a18763b77Svetoslav 815269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_MEDIA_SIZE = "mediaSize"; 816269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_RESOLUTION = "resolution"; 817269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String TAG_MARGINS = "margins"; 818269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 819269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_COLOR_MODE = "colorMode"; 820948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav private static final String ATTR_DUPLEX_MODE = "duplexMode"; 821269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 822704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov private static final String ATTR_LOCAL_ID = "localId"; 823269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_SERVICE_NAME = "serviceName"; 824269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 825269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_WIDTH_MILS = "widthMils"; 826269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_HEIGHT_MILS = "heightMils"; 827269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 828269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_HORIZONTAL_DPI = "horizontalDip"; 829269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_VERTICAL_DPI = "verticalDpi"; 830269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 831269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_LEFT_MILS = "leftMils"; 832269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_TOP_MILS = "topMils"; 833269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_RIGHT_MILS = "rightMils"; 834269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_BOTTOM_MILS = "bottomMils"; 835269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 836269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_START = "start"; 837269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_END = "end"; 838269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 839269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_NAME = "name"; 840269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_PAGE_COUNT = "pageCount"; 841269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private static final String ATTR_CONTENT_TYPE = "contentType"; 8427d7888d1c7daa78ee0ad24a24c8dd54b01749259Svetoslav Ganov private static final String ATTR_DATA_SIZE = "dataSize"; 843269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 844269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private final AtomicFile mStatePersistFile; 845269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 846269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private boolean mWriteStateScheduled; 847269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 848269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private PersistenceManager() { 849269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mStatePersistFile = new AtomicFile(new File(getFilesDir(), 850269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PERSIST_FILE_NAME)); 851269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 852269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 853269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public void writeStateLocked() { 8544237c92d850b7fb0fa0be15df94e4d1689e353fcSvet Ganov if (!PERSISTENCE_MANAGER_ENABLED) { 855269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return; 856269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 857269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (mWriteStateScheduled) { 858269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return; 859269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 860269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mWriteStateScheduled = true; 861269403b032f965ff3847eb982c2f697229dc5a92Svetoslav new AsyncTask<Void, Void, Void>() { 862269403b032f965ff3847eb982c2f697229dc5a92Svetoslav @Override 863269403b032f965ff3847eb982c2f697229dc5a92Svetoslav protected Void doInBackground(Void... params) { 864269403b032f965ff3847eb982c2f697229dc5a92Svetoslav synchronized (mLock) { 865269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mWriteStateScheduled = false; 866269403b032f965ff3847eb982c2f697229dc5a92Svetoslav doWriteStateLocked(); 867269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 868269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return null; 869269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 870269403b032f965ff3847eb982c2f697229dc5a92Svetoslav }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null); 871269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 872269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 873269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void doWriteStateLocked() { 874269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (DEBUG_PERSISTENCE) { 875269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.i(LOG_TAG, "[PERSIST START]"); 876269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 877269403b032f965ff3847eb982c2f697229dc5a92Svetoslav FileOutputStream out = null; 878269403b032f965ff3847eb982c2f697229dc5a92Svetoslav try { 879269403b032f965ff3847eb982c2f697229dc5a92Svetoslav out = mStatePersistFile.startWrite(); 880269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 881269403b032f965ff3847eb982c2f697229dc5a92Svetoslav XmlSerializer serializer = new FastXmlSerializer(); 8829e9e2e73c6ec7bece20268196dc89ad0c8bafad4Wojciech Staszkiewicz serializer.setOutput(out, StandardCharsets.UTF_8.name()); 883269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startDocument(null, true); 884269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_SPOOLER); 885269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 886269403b032f965ff3847eb982c2f697229dc5a92Svetoslav List<PrintJobInfo> printJobs = mPrintJobs; 887269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 888269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int printJobCount = printJobs.size(); 889269403b032f965ff3847eb982c2f697229dc5a92Svetoslav for (int j = 0; j < printJobCount; j++) { 890269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = printJobs.get(j); 891269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 892885810de69d75979df4299d21fa236490767eae4Svetoslav if (!shouldPersistPrintJob(printJob)) { 893885810de69d75979df4299d21fa236490767eae4Svetoslav continue; 894885810de69d75979df4299d21fa236490767eae4Svetoslav } 895885810de69d75979df4299d21fa236490767eae4Svetoslav 896269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_JOB); 897269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 8982fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav serializer.attribute(null, ATTR_ID, printJob.getId().flattenToString()); 899269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_LABEL, printJob.getLabel().toString()); 900269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_STATE, String.valueOf(printJob.getState())); 901269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_APP_ID, String.valueOf(printJob.getAppId())); 902269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String tag = printJob.getTag(); 903269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (tag != null) { 904269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_TAG, tag); 905269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 906704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov serializer.attribute(null, ATTR_CREATION_TIME, String.valueOf( 907704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov printJob.getCreationTime())); 908269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_COPIES, String.valueOf(printJob.getCopies())); 909704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov String printerName = printJob.getPrinterName(); 910704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (!TextUtils.isEmpty(printerName)) { 911704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov serializer.attribute(null, ATTR_PRINTER_NAME, printerName); 912704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 913a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov serializer.attribute(null, ATTR_CANCELLING, String.valueOf( 914a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov printJob.isCancelling())); 915269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 916b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann float progress = printJob.getProgress(); 917310ddc313fc1a1251c4ebd09868d5b4c7d0a3cf7Ian Rogers if (!Float.isNaN(progress)) { 918b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann serializer.attribute(null, ATTR_PROGRESS, String.valueOf(progress)); 919b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann } 920b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann 921d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann CharSequence status = printJob.getStatus(getPackageManager()); 922b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann if (!TextUtils.isEmpty(status)) { 923b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann serializer.attribute(null, ATTR_STATUS, status.toString()); 924b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann } 925b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann 926269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrinterId printerId = printJob.getPrinterId(); 927269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (printerId != null) { 928269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_PRINTER_ID); 929269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_LOCAL_ID, printerId.getLocalId()); 930269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_SERVICE_NAME, printerId.getServiceName() 931269403b032f965ff3847eb982c2f697229dc5a92Svetoslav .flattenToString()); 932269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_PRINTER_ID); 933269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 934269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 935269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PageRange[] pages = printJob.getPages(); 936269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (pages != null) { 937269403b032f965ff3847eb982c2f697229dc5a92Svetoslav for (int i = 0; i < pages.length; i++) { 938269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_PAGE_RANGE); 939269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_START, String.valueOf( 940269403b032f965ff3847eb982c2f697229dc5a92Svetoslav pages[i].getStart())); 941269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_END, String.valueOf( 942269403b032f965ff3847eb982c2f697229dc5a92Svetoslav pages[i].getEnd())); 943269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_PAGE_RANGE); 944269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 945269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 946269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 947269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintAttributes attributes = printJob.getAttributes(); 948269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (attributes != null) { 949269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_ATTRIBUTES); 950269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 951269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int colorMode = attributes.getColorMode(); 952269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_COLOR_MODE, 953269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String.valueOf(colorMode)); 954269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 955948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav final int duplexMode = attributes.getDuplexMode(); 956948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav serializer.attribute(null, ATTR_DUPLEX_MODE, 957948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav String.valueOf(duplexMode)); 958948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav 959269403b032f965ff3847eb982c2f697229dc5a92Svetoslav MediaSize mediaSize = attributes.getMediaSize(); 960269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (mediaSize != null) { 961269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_MEDIA_SIZE); 962269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_ID, mediaSize.getId()); 963269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_WIDTH_MILS, String.valueOf( 964269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mediaSize.getWidthMils())); 965269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_HEIGHT_MILS, String.valueOf( 966269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mediaSize.getHeightMils())); 967a76233ae845da4bc9e3bcd89821701a747215e7bSvetoslav // We prefer to store only the package name and 968a76233ae845da4bc9e3bcd89821701a747215e7bSvetoslav // resource id and fallback to the label. 969a76233ae845da4bc9e3bcd89821701a747215e7bSvetoslav if (!TextUtils.isEmpty(mediaSize.mPackageName) 970773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav && mediaSize.mLabelResId > 0) { 971773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav serializer.attribute(null, ATTR_PACKAGE_NAME, 972773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav mediaSize.mPackageName); 973773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav serializer.attribute(null, ATTR_LABEL_RES_ID, 974773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav String.valueOf(mediaSize.mLabelResId)); 975773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav } else { 976773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav serializer.attribute(null, ATTR_LABEL, 977773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav mediaSize.getLabel(getPackageManager())); 978773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav } 979269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_MEDIA_SIZE); 980269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 981269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 982269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Resolution resolution = attributes.getResolution(); 983269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (resolution != null) { 984269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_RESOLUTION); 985269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_ID, resolution.getId()); 986269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_HORIZONTAL_DPI, String.valueOf( 987269403b032f965ff3847eb982c2f697229dc5a92Svetoslav resolution.getHorizontalDpi())); 988269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_VERTICAL_DPI, String.valueOf( 989269403b032f965ff3847eb982c2f697229dc5a92Svetoslav resolution.getVerticalDpi())); 990c6066799ad130140159230d14451b429eb828755Svetoslav serializer.attribute(null, ATTR_LABEL, 991651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav resolution.getLabel()); 992269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_RESOLUTION); 993269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 994269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 995651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav Margins margins = attributes.getMinMargins(); 996269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (margins != null) { 997269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_MARGINS); 998269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_LEFT_MILS, String.valueOf( 999269403b032f965ff3847eb982c2f697229dc5a92Svetoslav margins.getLeftMils())); 1000269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_TOP_MILS, String.valueOf( 1001269403b032f965ff3847eb982c2f697229dc5a92Svetoslav margins.getTopMils())); 1002269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_RIGHT_MILS, String.valueOf( 1003269403b032f965ff3847eb982c2f697229dc5a92Svetoslav margins.getRightMils())); 1004269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_BOTTOM_MILS, String.valueOf( 1005269403b032f965ff3847eb982c2f697229dc5a92Svetoslav margins.getBottomMils())); 1006269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_MARGINS); 1007269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1008269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1009269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_ATTRIBUTES); 1010269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1011269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1012269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintDocumentInfo documentInfo = printJob.getDocumentInfo(); 1013269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (documentInfo != null) { 1014269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.startTag(null, TAG_DOCUMENT_INFO); 1015269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_NAME, documentInfo.getName()); 1016269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_CONTENT_TYPE, String.valueOf( 1017269403b032f965ff3847eb982c2f697229dc5a92Svetoslav documentInfo.getContentType())); 1018269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.attribute(null, ATTR_PAGE_COUNT, String.valueOf( 1019269403b032f965ff3847eb982c2f697229dc5a92Svetoslav documentInfo.getPageCount())); 10207d7888d1c7daa78ee0ad24a24c8dd54b01749259Svetoslav Ganov serializer.attribute(null, ATTR_DATA_SIZE, String.valueOf( 10217d7888d1c7daa78ee0ad24a24c8dd54b01749259Svetoslav Ganov documentInfo.getDataSize())); 1022269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_DOCUMENT_INFO); 1023269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1024269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1025b4fda134761c9521a7e127db3806a07a18763b77Svetoslav Bundle advancedOptions = printJob.getAdvancedOptions(); 1026b4fda134761c9521a7e127db3806a07a18763b77Svetoslav if (advancedOptions != null) { 1027b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.startTag(null, TAG_ADVANCED_OPTIONS); 1028b4fda134761c9521a7e127db3806a07a18763b77Svetoslav for (String key : advancedOptions.keySet()) { 1029b4fda134761c9521a7e127db3806a07a18763b77Svetoslav Object value = advancedOptions.get(key); 1030b4fda134761c9521a7e127db3806a07a18763b77Svetoslav if (value instanceof String) { 1031b4fda134761c9521a7e127db3806a07a18763b77Svetoslav String stringValue = (String) value; 1032b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.startTag(null, TAG_ADVANCED_OPTION); 1033b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.attribute(null, ATTR_KEY, key); 1034b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.attribute(null, ATTR_TYPE, TYPE_STRING); 1035b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.attribute(null, ATTR_VALUE, stringValue); 1036b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.endTag(null, TAG_ADVANCED_OPTION); 1037b4fda134761c9521a7e127db3806a07a18763b77Svetoslav } else if (value instanceof Integer) { 1038b4fda134761c9521a7e127db3806a07a18763b77Svetoslav String intValue = Integer.toString((Integer) value); 1039b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.startTag(null, TAG_ADVANCED_OPTION); 1040b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.attribute(null, ATTR_KEY, key); 1041b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.attribute(null, ATTR_TYPE, TYPE_INT); 1042b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.attribute(null, ATTR_VALUE, intValue); 1043b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.endTag(null, TAG_ADVANCED_OPTION); 1044b4fda134761c9521a7e127db3806a07a18763b77Svetoslav } 1045b4fda134761c9521a7e127db3806a07a18763b77Svetoslav } 1046b4fda134761c9521a7e127db3806a07a18763b77Svetoslav serializer.endTag(null, TAG_ADVANCED_OPTIONS); 1047b4fda134761c9521a7e127db3806a07a18763b77Svetoslav } 1048b4fda134761c9521a7e127db3806a07a18763b77Svetoslav 1049269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_JOB); 1050269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1051269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (DEBUG_PERSISTENCE) { 1052269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.i(LOG_TAG, "[PERSISTED] " + printJob); 1053269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1054269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1055269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1056269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endTag(null, TAG_SPOOLER); 1057269403b032f965ff3847eb982c2f697229dc5a92Svetoslav serializer.endDocument(); 1058269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mStatePersistFile.finishWrite(out); 1059269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (DEBUG_PERSISTENCE) { 1060269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.i(LOG_TAG, "[PERSIST END]"); 1061269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1062269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (IOException e) { 1063269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.w(LOG_TAG, "Failed to write state, restoring backup.", e); 1064269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mStatePersistFile.failWrite(out); 1065269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } finally { 1066269403b032f965ff3847eb982c2f697229dc5a92Svetoslav IoUtils.closeQuietly(out); 1067269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1068269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1069269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1070269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public void readStateLocked() { 10714237c92d850b7fb0fa0be15df94e4d1689e353fcSvet Ganov if (!PERSISTENCE_MANAGER_ENABLED) { 1072269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return; 1073269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1074269403b032f965ff3847eb982c2f697229dc5a92Svetoslav FileInputStream in = null; 1075269403b032f965ff3847eb982c2f697229dc5a92Svetoslav try { 1076269403b032f965ff3847eb982c2f697229dc5a92Svetoslav in = mStatePersistFile.openRead(); 1077269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (FileNotFoundException e) { 107813460a6cba25b99c405d00bb40939958df332f3fJoe Onorato if (DEBUG_PERSISTENCE) { 107913460a6cba25b99c405d00bb40939958df332f3fJoe Onorato Log.d(LOG_TAG, "No existing print spooler state."); 108013460a6cba25b99c405d00bb40939958df332f3fJoe Onorato } 1081269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return; 1082269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1083269403b032f965ff3847eb982c2f697229dc5a92Svetoslav try { 1084269403b032f965ff3847eb982c2f697229dc5a92Svetoslav XmlPullParser parser = Xml.newPullParser(); 10859e9e2e73c6ec7bece20268196dc89ad0c8bafad4Wojciech Staszkiewicz parser.setInput(in, StandardCharsets.UTF_8.name()); 1086269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parseState(parser); 1087269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (IllegalStateException ise) { 1088269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.w(LOG_TAG, "Failed parsing ", ise); 1089269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (NullPointerException npe) { 1090269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.w(LOG_TAG, "Failed parsing ", npe); 1091269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (NumberFormatException nfe) { 1092269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.w(LOG_TAG, "Failed parsing ", nfe); 1093269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (XmlPullParserException xppe) { 1094269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.w(LOG_TAG, "Failed parsing ", xppe); 1095269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (IOException ioe) { 1096269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.w(LOG_TAG, "Failed parsing ", ioe); 1097269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } catch (IndexOutOfBoundsException iobe) { 1098269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Slog.w(LOG_TAG, "Failed parsing ", iobe); 1099269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } finally { 1100269403b032f965ff3847eb982c2f697229dc5a92Svetoslav IoUtils.closeQuietly(in); 1101269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1102269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1103269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1104269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void parseState(XmlPullParser parser) 1105269403b032f965ff3847eb982c2f697229dc5a92Svetoslav throws IOException, XmlPullParserException { 1106269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1107269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1108269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.START_TAG, TAG_SPOOLER); 1109269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1110269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1111269403b032f965ff3847eb982c2f697229dc5a92Svetoslav while (parsePrintJob(parser)) { 1112269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1113269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1114269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1115269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1116269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_SPOOLER); 1117269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1118269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1119269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private boolean parsePrintJob(XmlPullParser parser) 1120269403b032f965ff3847eb982c2f697229dc5a92Svetoslav throws IOException, XmlPullParserException { 1121269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1122269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (!accept(parser, XmlPullParser.START_TAG, TAG_JOB)) { 1123269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 1124269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1125269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1126269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintJobInfo printJob = new PrintJobInfo(); 1127269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 11282fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav PrintJobId printJobId = PrintJobId.unflattenFromString( 11292fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav parser.getAttributeValue(null, ATTR_ID)); 1130269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setId(printJobId); 1131269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String label = parser.getAttributeValue(null, ATTR_LABEL); 1132269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setLabel(label); 1133269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int state = Integer.parseInt(parser.getAttributeValue(null, ATTR_STATE)); 1134269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setState(state); 1135269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int appId = Integer.parseInt(parser.getAttributeValue(null, ATTR_APP_ID)); 1136269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setAppId(appId); 1137269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String tag = parser.getAttributeValue(null, ATTR_TAG); 1138269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setTag(tag); 1139704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov String creationTime = parser.getAttributeValue(null, ATTR_CREATION_TIME); 1140704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov printJob.setCreationTime(Long.parseLong(creationTime)); 1141269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String copies = parser.getAttributeValue(null, ATTR_COPIES); 1142269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setCopies(Integer.parseInt(copies)); 1143704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov String printerName = parser.getAttributeValue(null, ATTR_PRINTER_NAME); 1144704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov printJob.setPrinterName(printerName); 1145b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann 1146b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann String progressString = parser.getAttributeValue(null, ATTR_PROGRESS); 1147b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann if (progressString != null) { 1148b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann float progress = Float.parseFloat(progressString); 1149b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann 1150a958fc336b277cf2838ccd50ef3d3484644b100aPhilip P. Moltmann if (progress != -1) { 1151b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann printJob.setProgress(progress); 1152b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann } 1153b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann } 1154b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann 1155b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann CharSequence status = parser.getAttributeValue(null, ATTR_STATUS); 1156b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann printJob.setStatus(status); 1157b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann 1158b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann // stateReason is deprecated, but might be used by old print jobs 1159704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov String stateReason = parser.getAttributeValue(null, ATTR_STATE_REASON); 1160b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann if (stateReason != null) { 1161b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann printJob.setStatus(stateReason); 1162b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann } 1163b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann 1164a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov String cancelling = parser.getAttributeValue(null, ATTR_CANCELLING); 1165a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov printJob.setCancelling(!TextUtils.isEmpty(cancelling) 1166a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov ? Boolean.parseBoolean(cancelling) : false); 1167269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1168269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1169269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1170269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1171269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (accept(parser, XmlPullParser.START_TAG, TAG_PRINTER_ID)) { 1172269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String localId = parser.getAttributeValue(null, ATTR_LOCAL_ID); 1173269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ComponentName service = ComponentName.unflattenFromString(parser.getAttributeValue( 1174269403b032f965ff3847eb982c2f697229dc5a92Svetoslav null, ATTR_SERVICE_NAME)); 1175269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setPrinterId(new PrinterId(service, localId)); 1176269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1177269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1178269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_PRINTER_ID); 1179269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1180269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1181269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1182269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1183269403b032f965ff3847eb982c2f697229dc5a92Svetoslav List<PageRange> pageRanges = null; 1184269403b032f965ff3847eb982c2f697229dc5a92Svetoslav while (accept(parser, XmlPullParser.START_TAG, TAG_PAGE_RANGE)) { 1185269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int start = Integer.parseInt(parser.getAttributeValue(null, ATTR_START)); 1186269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int end = Integer.parseInt(parser.getAttributeValue(null, ATTR_END)); 1187269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PageRange pageRange = new PageRange(start, end); 1188269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (pageRanges == null) { 1189269403b032f965ff3847eb982c2f697229dc5a92Svetoslav pageRanges = new ArrayList<PageRange>(); 1190269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1191269403b032f965ff3847eb982c2f697229dc5a92Svetoslav pageRanges.add(pageRange); 1192269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1193269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1194269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_PAGE_RANGE); 1195269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1196b4fda134761c9521a7e127db3806a07a18763b77Svetoslav skipEmptyTextTags(parser); 1197269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1198269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (pageRanges != null) { 1199269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PageRange[] pageRangesArray = new PageRange[pageRanges.size()]; 1200269403b032f965ff3847eb982c2f697229dc5a92Svetoslav pageRanges.toArray(pageRangesArray); 1201269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setPages(pageRangesArray); 1202269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1203269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1204269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1205269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (accept(parser, XmlPullParser.START_TAG, TAG_ATTRIBUTES)) { 1206269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1207269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintAttributes.Builder builder = new PrintAttributes.Builder(); 1208269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1209269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String colorMode = parser.getAttributeValue(null, ATTR_COLOR_MODE); 1210269403b032f965ff3847eb982c2f697229dc5a92Svetoslav builder.setColorMode(Integer.parseInt(colorMode)); 1211269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1212948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav String duplexMode = parser.getAttributeValue(null, ATTR_DUPLEX_MODE); 1213948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav // Duplex mode was added later, so null check is needed. 1214948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav if (duplexMode != null) { 1215948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav builder.setDuplexMode(Integer.parseInt(duplexMode)); 1216948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav } 1217948c9a6393e0995a4d988d5d164998aa0e12b25dSvetoslav 1218269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1219269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1220269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1221269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (accept(parser, XmlPullParser.START_TAG, TAG_MEDIA_SIZE)) { 1222269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String id = parser.getAttributeValue(null, ATTR_ID); 1223269403b032f965ff3847eb982c2f697229dc5a92Svetoslav label = parser.getAttributeValue(null, ATTR_LABEL); 1224269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int widthMils = Integer.parseInt(parser.getAttributeValue(null, 1225269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_WIDTH_MILS)); 1226269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int heightMils = Integer.parseInt(parser.getAttributeValue(null, 1227269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_HEIGHT_MILS)); 1228773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav String packageName = parser.getAttributeValue(null, ATTR_PACKAGE_NAME); 1229b206f1271d17164c3f2f65219eee7a0b4b4fa6dcSvetoslav String labelResIdString = parser.getAttributeValue(null, ATTR_LABEL_RES_ID); 1230b206f1271d17164c3f2f65219eee7a0b4b4fa6dcSvetoslav final int labelResId = (labelResIdString != null) 1231b206f1271d17164c3f2f65219eee7a0b4b4fa6dcSvetoslav ? Integer.parseInt(labelResIdString) : 0; 1232773f54de3de9bce7b6f915aa47ed686b161d77aaSvetoslav label = parser.getAttributeValue(null, ATTR_LABEL); 1233b4fda134761c9521a7e127db3806a07a18763b77Svetoslav MediaSize mediaSize = new MediaSize(id, label, packageName, 1234b4fda134761c9521a7e127db3806a07a18763b77Svetoslav widthMils, heightMils, labelResId); 1235269403b032f965ff3847eb982c2f697229dc5a92Svetoslav builder.setMediaSize(mediaSize); 1236269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1237269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1238269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_MEDIA_SIZE); 1239269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1240269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1241269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1242269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1243269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (accept(parser, XmlPullParser.START_TAG, TAG_RESOLUTION)) { 1244269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String id = parser.getAttributeValue(null, ATTR_ID); 1245269403b032f965ff3847eb982c2f697229dc5a92Svetoslav label = parser.getAttributeValue(null, ATTR_LABEL); 1246269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int horizontalDpi = Integer.parseInt(parser.getAttributeValue(null, 1247269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_HORIZONTAL_DPI)); 1248269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int verticalDpi = Integer.parseInt(parser.getAttributeValue(null, 1249269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_VERTICAL_DPI)); 1250c6066799ad130140159230d14451b429eb828755Svetoslav Resolution resolution = new Resolution(id, label, horizontalDpi, verticalDpi); 1251269403b032f965ff3847eb982c2f697229dc5a92Svetoslav builder.setResolution(resolution); 1252269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1253269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1254269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_RESOLUTION); 1255269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1256269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1257269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1258269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1259269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (accept(parser, XmlPullParser.START_TAG, TAG_MARGINS)) { 1260269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int leftMils = Integer.parseInt(parser.getAttributeValue(null, 1261269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_LEFT_MILS)); 1262269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int topMils = Integer.parseInt(parser.getAttributeValue(null, 1263269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_TOP_MILS)); 1264269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int rightMils = Integer.parseInt(parser.getAttributeValue(null, 1265269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_RIGHT_MILS)); 1266269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int bottomMils = Integer.parseInt(parser.getAttributeValue(null, 1267269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_BOTTOM_MILS)); 1268269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Margins margins = new Margins(leftMils, topMils, rightMils, bottomMils); 1269651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav builder.setMinMargins(margins); 1270269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1271269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1272269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_MARGINS); 1273269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1274269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1275269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1276651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav printJob.setAttributes(builder.build()); 1277269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1278269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1279269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_ATTRIBUTES); 1280269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1281269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1282269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1283269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1284269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (accept(parser, XmlPullParser.START_TAG, TAG_DOCUMENT_INFO)) { 1285269403b032f965ff3847eb982c2f697229dc5a92Svetoslav String name = parser.getAttributeValue(null, ATTR_NAME); 1286269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int pageCount = Integer.parseInt(parser.getAttributeValue(null, 1287269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_PAGE_COUNT)); 1288269403b032f965ff3847eb982c2f697229dc5a92Svetoslav final int contentType = Integer.parseInt(parser.getAttributeValue(null, 1289269403b032f965ff3847eb982c2f697229dc5a92Svetoslav ATTR_CONTENT_TYPE)); 12907d7888d1c7daa78ee0ad24a24c8dd54b01749259Svetoslav Ganov final int dataSize = Integer.parseInt(parser.getAttributeValue(null, 12917d7888d1c7daa78ee0ad24a24c8dd54b01749259Svetoslav Ganov ATTR_DATA_SIZE)); 1292269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrintDocumentInfo info = new PrintDocumentInfo.Builder(name) 1293269403b032f965ff3847eb982c2f697229dc5a92Svetoslav .setPageCount(pageCount) 1294651dd4e6ee6510caf9f15c51094a11121af17ec2Svetoslav .setContentType(contentType).build(); 1295269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJob.setDocumentInfo(info); 12967d7888d1c7daa78ee0ad24a24c8dd54b01749259Svetoslav Ganov info.setDataSize(dataSize); 1297269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1298269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1299269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_DOCUMENT_INFO); 1300269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1301269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1302269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1303b4fda134761c9521a7e127db3806a07a18763b77Svetoslav skipEmptyTextTags(parser); 1304b4fda134761c9521a7e127db3806a07a18763b77Svetoslav if (accept(parser, XmlPullParser.START_TAG, TAG_ADVANCED_OPTIONS)) { 1305b4fda134761c9521a7e127db3806a07a18763b77Svetoslav parser.next(); 1306b4fda134761c9521a7e127db3806a07a18763b77Svetoslav skipEmptyTextTags(parser); 1307b4fda134761c9521a7e127db3806a07a18763b77Svetoslav Bundle advancedOptions = new Bundle(); 1308b4fda134761c9521a7e127db3806a07a18763b77Svetoslav while (accept(parser, XmlPullParser.START_TAG, TAG_ADVANCED_OPTION)) { 1309b4fda134761c9521a7e127db3806a07a18763b77Svetoslav String key = parser.getAttributeValue(null, ATTR_KEY); 1310b4fda134761c9521a7e127db3806a07a18763b77Svetoslav String value = parser.getAttributeValue(null, ATTR_VALUE); 1311b4fda134761c9521a7e127db3806a07a18763b77Svetoslav String type = parser.getAttributeValue(null, ATTR_TYPE); 1312b4fda134761c9521a7e127db3806a07a18763b77Svetoslav if (TYPE_STRING.equals(type)) { 1313b4fda134761c9521a7e127db3806a07a18763b77Svetoslav advancedOptions.putString(key, value); 1314b4fda134761c9521a7e127db3806a07a18763b77Svetoslav } else if (TYPE_INT.equals(type)) { 13159bbbf2b15f331e8c72ee1054dc0ef6a613921fe1Tobias Thierer advancedOptions.putInt(key, Integer.parseInt(value)); 1316b4fda134761c9521a7e127db3806a07a18763b77Svetoslav } 1317b4fda134761c9521a7e127db3806a07a18763b77Svetoslav parser.next(); 1318b4fda134761c9521a7e127db3806a07a18763b77Svetoslav skipEmptyTextTags(parser); 1319b4fda134761c9521a7e127db3806a07a18763b77Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_ADVANCED_OPTION); 1320b4fda134761c9521a7e127db3806a07a18763b77Svetoslav parser.next(); 1321b4fda134761c9521a7e127db3806a07a18763b77Svetoslav skipEmptyTextTags(parser); 1322b4fda134761c9521a7e127db3806a07a18763b77Svetoslav } 1323b4fda134761c9521a7e127db3806a07a18763b77Svetoslav printJob.setAdvancedOptions(advancedOptions); 1324b4fda134761c9521a7e127db3806a07a18763b77Svetoslav skipEmptyTextTags(parser); 1325b4fda134761c9521a7e127db3806a07a18763b77Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_ADVANCED_OPTIONS); 1326b4fda134761c9521a7e127db3806a07a18763b77Svetoslav parser.next(); 1327b4fda134761c9521a7e127db3806a07a18763b77Svetoslav } 1328b4fda134761c9521a7e127db3806a07a18763b77Svetoslav 1329269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mPrintJobs.add(printJob); 1330269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1331269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (DEBUG_PERSISTENCE) { 1332269403b032f965ff3847eb982c2f697229dc5a92Svetoslav Log.i(LOG_TAG, "[RESTORED] " + printJob); 1333269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1334269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1335269403b032f965ff3847eb982c2f697229dc5a92Svetoslav skipEmptyTextTags(parser); 1336269403b032f965ff3847eb982c2f697229dc5a92Svetoslav expect(parser, XmlPullParser.END_TAG, TAG_JOB); 1337269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1338269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return true; 1339269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1340269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1341269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void expect(XmlPullParser parser, int type, String tag) 1342c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann throws XmlPullParserException { 1343269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (!accept(parser, type, tag)) { 1344269403b032f965ff3847eb982c2f697229dc5a92Svetoslav throw new XmlPullParserException("Exepected event: " + type 1345269403b032f965ff3847eb982c2f697229dc5a92Svetoslav + " and tag: " + tag + " but got event: " + parser.getEventType() 1346269403b032f965ff3847eb982c2f697229dc5a92Svetoslav + " and tag:" + parser.getName()); 1347269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1348269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1349269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1350269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private void skipEmptyTextTags(XmlPullParser parser) 1351269403b032f965ff3847eb982c2f697229dc5a92Svetoslav throws IOException, XmlPullParserException { 1352269403b032f965ff3847eb982c2f697229dc5a92Svetoslav while (accept(parser, XmlPullParser.TEXT, null) 1353269403b032f965ff3847eb982c2f697229dc5a92Svetoslav && "\n".equals(parser.getText())) { 1354269403b032f965ff3847eb982c2f697229dc5a92Svetoslav parser.next(); 1355269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1356269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1357269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 1358269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private boolean accept(XmlPullParser parser, int type, String tag) 1359c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann throws XmlPullParserException { 1360269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (parser.getEventType() != type) { 1361269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 1362269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1363269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (tag != null) { 1364269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (!tag.equals(parser.getName())) { 1365269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 1366269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1367269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } else if (parser.getName() != null) { 1368269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return false; 1369269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1370269403b032f965ff3847eb982c2f697229dc5a92Svetoslav return true; 1371269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 1372269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 13737bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 1374a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public final class PrintSpooler extends IPrintSpooler.Stub { 13757bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 13767bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void getPrintJobInfos(IPrintSpoolerCallbacks callback, 13777bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav ComponentName componentName, int state, int appId, int sequence) 13787bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav throws RemoteException { 13797bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav List<PrintJobInfo> printJobs = null; 13807bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav try { 13817bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav printJobs = PrintSpoolerService.this.getPrintJobInfos( 13827bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav componentName, state, appId); 13837bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } finally { 13847bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav callback.onGetPrintJobInfosResult(printJobs, sequence); 13857bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 13867bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 13877bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 13887bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 13897bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void getPrintJobInfo(PrintJobId printJobId, IPrintSpoolerCallbacks callback, 13907bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav int appId, int sequence) throws RemoteException { 13917bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav PrintJobInfo printJob = null; 13927bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav try { 13937bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav printJob = PrintSpoolerService.this.getPrintJobInfo(printJobId, appId); 13947bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } finally { 13957bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav callback.onGetPrintJobInfoResult(printJob, sequence); 13967bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 13977bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 13987bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 13997bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 14007bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void createPrintJob(PrintJobInfo printJob) { 14017bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav PrintSpoolerService.this.createPrintJob(printJob); 14027bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 14037bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 14047bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 14057bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void setPrintJobState(PrintJobId printJobId, int state, String error, 14067bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav IPrintSpoolerCallbacks callback, int sequece) throws RemoteException { 14077bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav boolean success = false; 14087bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav try { 14097bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav success = PrintSpoolerService.this.setPrintJobState( 14107bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav printJobId, state, error); 14117bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } finally { 14127bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav callback.onSetPrintJobStateResult(success, sequece); 14137bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 14147bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 14157bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 14167bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 14177bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void setPrintJobTag(PrintJobId printJobId, String tag, 14187bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav IPrintSpoolerCallbacks callback, int sequece) throws RemoteException { 14197bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav boolean success = false; 14207bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav try { 14217bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav success = PrintSpoolerService.this.setPrintJobTag(printJobId, tag); 14227bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } finally { 14237bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav callback.onSetPrintJobTagResult(success, sequece); 14247bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 14257bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 14267bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 14277bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 14287bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void writePrintJobData(ParcelFileDescriptor fd, PrintJobId printJobId) { 14297bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav PrintSpoolerService.this.writePrintJobData(fd, printJobId); 14307bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 14317bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 14327bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 14337bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void setClient(IPrintSpoolerClient client) { 14347bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav Message message = mHandlerCaller.obtainMessageO( 14357bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav HandlerCallerCallback.MSG_SET_CLIENT, client); 14367bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav mHandlerCaller.executeOrSendMessage(message); 14377bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 14387bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 14397bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 14407bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void removeObsoletePrintJobs() { 14417bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav PrintSpoolerService.this.removeObsoletePrintJobs(); 14427bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 14437bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 14447bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 14457bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 14467bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav PrintSpoolerService.this.dump(fd, writer, args); 14477bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 14487bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 14497bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav @Override 14507bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public void setPrintJobCancelling(PrintJobId printJobId, boolean cancelling) { 14517bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav PrintSpoolerService.this.setPrintJobCancelling(printJobId, cancelling); 14527bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 14537bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 1454853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann @Override 14558141bdfa56f13c3946bed12ba7801e492ec25c11Philip P. Moltmann public void pruneApprovedPrintServices(List<ComponentName> servicesToKeep) { 1456853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann (new ApprovedPrintServices(PrintSpoolerService.this)) 14578141bdfa56f13c3946bed12ba7801e492ec25c11Philip P. Moltmann .pruneApprovedServices(servicesToKeep); 1458853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann } 1459853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann 1460b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann @Override 1461b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann public void setProgress(@NonNull PrintJobId printJobId, 1462b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann @FloatRange(from=0.0, to=1.0) float progress) throws RemoteException { 1463b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann PrintSpoolerService.this.setProgress(printJobId, progress); 1464b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann } 1465b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann 1466b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann @Override 1467b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann public void setStatus(@NonNull PrintJobId printJobId, 1468b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann @Nullable CharSequence status) throws RemoteException { 1469b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann PrintSpoolerService.this.setStatus(printJobId, status); 1470b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann } 1471b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann 1472d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann @Override 1473d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann public void setStatusRes(@NonNull PrintJobId printJobId, @StringRes int status, 1474d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann @NonNull CharSequence appPackageName) throws RemoteException { 1475d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann PrintSpoolerService.this.setStatus(printJobId, status, appPackageName); 1476d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann } 1477d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann 1478d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann 14797bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public PrintSpoolerService getService() { 14807bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav return PrintSpoolerService.this; 14817bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 1482bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann 1483bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann @Override 1484bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann public void onCustomPrinterIconLoaded(PrinterId printerId, Icon icon, 1485bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann IPrintSpoolerCallbacks callbacks, int sequence) 1486bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann throws RemoteException { 1487bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann try { 1488bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann PrintSpoolerService.this.onCustomPrinterIconLoaded(printerId, icon); 1489bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann } finally { 1490bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann callbacks.onCustomPrinterIconCached(sequence); 1491bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann } 1492bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann } 1493bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann 1494bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann @Override 1495bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann public void getCustomPrinterIcon(PrinterId printerId, IPrintSpoolerCallbacks callbacks, 1496bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann int sequence) throws RemoteException { 1497bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann Icon icon = null; 1498bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann try { 1499bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann icon = PrintSpoolerService.this.getCustomPrinterIcon(printerId); 1500bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann } finally { 1501bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann callbacks.onGetCustomPrinterIconResult(icon, sequence); 1502bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann } 1503bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann } 1504bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann 1505bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann @Override 1506bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann public void clearCustomPrinterIconCache(IPrintSpoolerCallbacks callbacks, 1507bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann int sequence) throws RemoteException { 1508bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann try { 1509bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann PrintSpoolerService.this.clearCustomPrinterIconCache(); 1510bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann } finally { 1511bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann callbacks.customPrinterIconCacheCleared(sequence); 1512bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann } 1513bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann } 1514bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann 15157bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 15164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov} 1517