14b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/* 24b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Copyright (C) 2013 The Android Open Source Project 34b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 44b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Licensed under the Apache License, Version 2.0 (the "License"); 54b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * you may not use this file except in compliance with the License. 64b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * You may obtain a copy of the License at 74b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 84b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * http://www.apache.org/licenses/LICENSE-2.0 94b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Unless required by applicable law or agreed to in writing, software 114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * distributed under the License is distributed on an "AS IS" BASIS, 124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * See the License for the specific language governing permissions and 144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * limitations under the License. 154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovpackage android.print; 184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 19858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganovimport android.app.Activity; 20858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganovimport android.app.Application.ActivityLifecycleCallbacks; 214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.Context; 224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.IntentSender; 234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.IntentSender.SendIntentException; 246283608e0bd40548742839f5a8b02f7e5c9c5c7cSvetoslavimport android.os.Bundle; 254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.CancellationSignal; 264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Handler; 27a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.os.ICancellationSignal; 284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Looper; 294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Message; 304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.ParcelFileDescriptor; 314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.RemoteException; 32a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.PrintDocumentAdapter.LayoutResultCallback; 33a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.PrintDocumentAdapter.WriteResultCallback; 34860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganovimport android.printservice.PrintServiceInfo; 3588d199130d44c6bacb383a7757e782cf97483c68Svetoslav Ganovimport android.text.TextUtils; 36704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganovimport android.util.ArrayMap; 374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.util.Log; 384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport com.android.internal.os.SomeArgs; 404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport libcore.io.IoUtils; 424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.lang.ref.WeakReference; 444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.ArrayList; 45a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport java.util.Arrays; 464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.Collections; 474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.List; 48704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganovimport java.util.Map; 494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/** 514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * System level service for accessing the printing capabilities of the platform. 524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * To obtain a handle to the print manager do the following: 544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 55a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * 564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <pre> 574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * PrintManager printManager = 584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * (PrintManager) context.getSystemService(Context.PRINT_SERVICE); 594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </pre> 60a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * 614d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * <h3>Print mechanics</h3> 624d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * <p> 634d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * The key idea behind printing on the platform is that the content to be printed 644d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * should be laid out for the currently selected print options resulting in an 654d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * optimized output and higher user satisfaction. To achieve this goal the platform 664d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * declares a contract that the printing application has to follow which is defined 674d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * by the {@link PrintDocumentAdapter} class. At a higher level the contract is that 684d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * when the user selects some options from the print UI that may affect the way 694d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * content is laid out, for example page size, the application receives a callback 704d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * allowing it to layout the content to better fit these new constraints. After a 714d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * layout pass the system may ask the application to render one or more pages one 724d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * or more times. For example, an application may produce a single column list for 734d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * smaller page sizes and a multi-column table for larger page sizes. 744d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * </p> 754d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * <h3>Print jobs</h3> 764d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * <p> 774d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * Print jobs are started by calling the {@link #print(String, PrintDocumentAdapter, 784d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * PrintAttributes)} from an activity which results in bringing up the system print 794d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * UI. Once the print UI is up, when the user changes a selected print option that 804d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * affects the way content is laid out the system starts to interact with the 814d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * application following the mechanics described the section above. 824d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * </p> 834d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * <p> 844d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * Print jobs can be in {@link PrintJobInfo#STATE_CREATED created}, {@link 854d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * PrintJobInfo#STATE_QUEUED queued}, {@link PrintJobInfo#STATE_STARTED started}, 864d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * {@link PrintJobInfo#STATE_BLOCKED blocked}, {@link PrintJobInfo#STATE_COMPLETED 874d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * completed}, {@link PrintJobInfo#STATE_FAILED failed}, and {@link 884d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * PrintJobInfo#STATE_CANCELED canceled} state. Print jobs are stored in dedicated 894d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * system spooler until they are handled which is they are cancelled or completed. 904d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * Active print jobs, ones that are not cancelled or completed, are considered failed 914d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * if the device reboots as the new boot may be after a very long time. The user may 924d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * choose to restart such print jobs. Once a print job is queued all relevant content 934d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * is stored in the system spooler and its lifecycle becomes detached from this of 944d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * the application that created it. 954d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * </p> 964d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * <p> 974d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * An applications can query the print spooler for current print jobs it created 984d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * but not print jobs created by other applications. 994d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * </p> 1004d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * 1014d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * @see PrintJob 1024d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * @see PrintJobInfo 1034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 1044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovpublic final class PrintManager { 1054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private static final String LOG_TAG = "PrintManager"; 1074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 10815cbc8a03250eafdf947cd8ad4e77f34444d5ba4Svetoslav private static final boolean DEBUG = false; 109db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 1107bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav private static final int MSG_NOTIFY_PRINT_JOB_STATE_CHANGED = 1; 1117bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 1127bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav /** 1137bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * The action for launching the print dialog activity. 1147bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * 1157bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * @hide 1167bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav */ 1177bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final String ACTION_PRINT_DIALOG = "android.print.PRINT_DIALOG"; 1187bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 1197bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav /** 1207bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * Extra with the intent for starting the print dialog. 1217bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * <p> 1227bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * <strong>Type:</strong> {@link android.content.IntentSender} 1237bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * </p> 1247bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * 1257bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * @hide 1267bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav */ 1277bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final String EXTRA_PRINT_DIALOG_INTENT = 1287bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav "android.print.intent.extra.EXTRA_PRINT_DIALOG_INTENT"; 1297bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 1307bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav /** 1317bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * Extra with a print job. 1327bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * <p> 1337bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * <strong>Type:</strong> {@link android.print.PrintJobInfo} 1347bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * </p> 1357bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * 1367bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * @hide 1377bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav */ 1387bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final String EXTRA_PRINT_JOB = 1397bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav "android.print.intent.extra.EXTRA_PRINT_JOB"; 1407bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 1417bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav /** 1427bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * Extra with the print document adapter to be printed. 1437bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * <p> 1447bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * <strong>Type:</strong> {@link android.print.IPrintDocumentAdapter} 1457bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * </p> 1467bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * 1477bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * @hide 1487bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav */ 1497bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final String EXTRA_PRINT_DOCUMENT_ADAPTER = 1507bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav "android.print.intent.extra.EXTRA_PRINT_DOCUMENT_ADAPTER"; 151a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov 1524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** @hide */ 1534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public static final int APP_ID_ANY = -2; 1544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final Context mContext; 1564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final IPrintManager mService; 1584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final int mUserId; 1604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final int mAppId; 1624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final Handler mHandler; 1644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 165704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov private Map<PrintJobStateChangeListener, PrintJobStateChangeListenerWrapper> mPrintJobStateChangeListeners; 166704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 167704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov /** @hide */ 168704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov public interface PrintJobStateChangeListener { 169704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 170704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov /** 171704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * Callback notifying that a print job state changed. 1722235a1772fc3c72b5c1795310e221d613cae01daSvetoslav * 173704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * @param printJobId The print job id. 174704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov */ 175a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov public void onPrintJobStateChanged(PrintJobId printJobId); 176704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 177704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 1784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 1794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Creates a new instance. 1802235a1772fc3c72b5c1795310e221d613cae01daSvetoslav * 1814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @param context The current context in which to operate. 1824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @param service The backing system service. 1834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @hide 1844b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 1854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public PrintManager(Context context, IPrintManager service, int userId, int appId) { 1864b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mContext = context; 1874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mService = service; 1884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mUserId = userId; 1894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mAppId = appId; 1904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mHandler = new Handler(context.getMainLooper(), null, false) { 1914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 1924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void handleMessage(Message message) { 193a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov switch (message.what) { 194a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov case MSG_NOTIFY_PRINT_JOB_STATE_CHANGED: { 195a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov SomeArgs args = (SomeArgs) message.obj; 196d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov PrintJobStateChangeListenerWrapper wrapper = 197d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov (PrintJobStateChangeListenerWrapper) args.arg1; 198d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov PrintJobStateChangeListener listener = wrapper.getListener(); 199d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov if (listener != null) { 200d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov PrintJobId printJobId = (PrintJobId) args.arg2; 201d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov listener.onPrintJobStateChanged(printJobId); 202d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov } 203a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov args.recycle(); 2047bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } break; 2054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov }; 2084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 2114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Creates an instance that can access all print jobs. 2122235a1772fc3c72b5c1795310e221d613cae01daSvetoslav * 2134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @param userId The user id for which to get all print jobs. 214a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov * @return An instance if the caller has the permission to access all print 215a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov * jobs, null otherwise. 2164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @hide 2174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 2184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public PrintManager getGlobalPrintManagerForUser(int userId) { 2192235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 2202235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 2212235a1772fc3c72b5c1795310e221d613cae01daSvetoslav return null; 2222235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 2234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return new PrintManager(mContext, mService, userId, APP_ID_ANY); 2244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2262fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav PrintJobInfo getPrintJobInfo(PrintJobId printJobId) { 2274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov try { 228a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return mService.getPrintJobInfo(printJobId, mAppId, mUserId); 2294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } catch (RemoteException re) { 230a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Log.e(LOG_TAG, "Error getting a print job info:" + printJobId, re); 2314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return null; 2334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 236704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * Adds a listener for observing the state of print jobs. 2372235a1772fc3c72b5c1795310e221d613cae01daSvetoslav * 238704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * @param listener The listener to add. 239704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * @hide 240704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov */ 241704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov public void addPrintJobStateChangeListener(PrintJobStateChangeListener listener) { 2422235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 2432235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 2442235a1772fc3c72b5c1795310e221d613cae01daSvetoslav return; 2452235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 246704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (mPrintJobStateChangeListeners == null) { 247704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov mPrintJobStateChangeListeners = new ArrayMap<PrintJobStateChangeListener, 248704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov PrintJobStateChangeListenerWrapper>(); 249704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 250704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov PrintJobStateChangeListenerWrapper wrappedListener = 251a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov new PrintJobStateChangeListenerWrapper(listener, mHandler); 252704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov try { 253704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov mService.addPrintJobStateChangeListener(wrappedListener, mAppId, mUserId); 254704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov mPrintJobStateChangeListeners.put(listener, wrappedListener); 255704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } catch (RemoteException re) { 256704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov Log.e(LOG_TAG, "Error adding print job state change listener", re); 257704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 258704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 259704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 260704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov /** 261704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * Removes a listener for observing the state of print jobs. 2622235a1772fc3c72b5c1795310e221d613cae01daSvetoslav * 263704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * @param listener The listener to remove. 264704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * @hide 265704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov */ 266704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov public void removePrintJobStateChangeListener(PrintJobStateChangeListener listener) { 2672235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 2682235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 2692235a1772fc3c72b5c1795310e221d613cae01daSvetoslav return; 2702235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 271704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (mPrintJobStateChangeListeners == null) { 272704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov return; 273704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 274704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov PrintJobStateChangeListenerWrapper wrappedListener = 275704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov mPrintJobStateChangeListeners.remove(listener); 276704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (wrappedListener == null) { 277704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov return; 278704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 279704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (mPrintJobStateChangeListeners.isEmpty()) { 280704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov mPrintJobStateChangeListeners = null; 281704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 282d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov wrappedListener.destroy(); 283704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov try { 284704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov mService.removePrintJobStateChangeListener(wrappedListener, mUserId); 285704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } catch (RemoteException re) { 286704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov Log.e(LOG_TAG, "Error removing print job state change listener", re); 287704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 288704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 289704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 290704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov /** 291704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * Gets a print job given its id. 2922235a1772fc3c72b5c1795310e221d613cae01daSvetoslav * 293704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * @return The print job list. 294704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * @see PrintJob 295704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * @hide 296704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov */ 297704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov public PrintJob getPrintJob(PrintJobId printJobId) { 2982235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 2992235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 3002235a1772fc3c72b5c1795310e221d613cae01daSvetoslav return null; 3012235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 302704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov try { 303704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov PrintJobInfo printJob = mService.getPrintJobInfo(printJobId, mAppId, mUserId); 304704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (printJob != null) { 305704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov return new PrintJob(printJob, this); 306704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 307704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } catch (RemoteException re) { 308704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov Log.e(LOG_TAG, "Error getting print job", re); 309704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 310704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov return null; 311704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 312704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 313704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov /** 3144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Gets the print jobs for this application. 3152235a1772fc3c72b5c1795310e221d613cae01daSvetoslav * 3164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @return The print job list. 3174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @see PrintJob 3184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 3194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public List<PrintJob> getPrintJobs() { 3202235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 3212235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 3222235a1772fc3c72b5c1795310e221d613cae01daSvetoslav return Collections.emptyList(); 3232235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 3244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov try { 325a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov List<PrintJobInfo> printJobInfos = mService.getPrintJobInfos(mAppId, mUserId); 3264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (printJobInfos == null) { 3274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return Collections.emptyList(); 3284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov final int printJobCount = printJobInfos.size(); 3304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov List<PrintJob> printJobs = new ArrayList<PrintJob>(printJobCount); 3314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov for (int i = 0; i < printJobCount; i++) { 3324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov printJobs.add(new PrintJob(printJobInfos.get(i), this)); 3334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return printJobs; 3354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } catch (RemoteException re) { 336a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Log.e(LOG_TAG, "Error getting print jobs", re); 3374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return Collections.emptyList(); 3394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 3412fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav void cancelPrintJob(PrintJobId printJobId) { 3422235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 3432235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 3442235a1772fc3c72b5c1795310e221d613cae01daSvetoslav return; 3452235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 3464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov try { 3474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mService.cancelPrintJob(printJobId, mAppId, mUserId); 3484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } catch (RemoteException re) { 349a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "Error canceling a print job: " + printJobId, re); 3504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 353704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov void restartPrintJob(PrintJobId printJobId) { 3542235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 3552235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 3562235a1772fc3c72b5c1795310e221d613cae01daSvetoslav return; 3572235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 358704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov try { 359704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov mService.restartPrintJob(printJobId, mAppId, mUserId); 360704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } catch (RemoteException re) { 361704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov Log.e(LOG_TAG, "Error restarting a print job: " + printJobId, re); 362704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 363704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 364704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 3654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 366a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov * Creates a print job for printing a {@link PrintDocumentAdapter} with 367a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov * default print attributes. 3684d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * <p> 3694d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * Calling this method brings the print UI allowing the user to customize 3704d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * the print job and returns a {@link PrintJob} object without waiting for the 3714d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * user to customize or confirm the print job. The returned print job instance 3724d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * is in a {@link PrintJobInfo#STATE_CREATED created} state. 3734d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * <p> 3744d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * This method can be called only from an {@link Activity}. The rationale is that 3754d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * printing from a service will create an inconsistent user experience as the print 3764d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * UI would appear without any context. 3774d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * </p> 3784d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * <p> 3794d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * Also the passed in {@link PrintDocumentAdapter} will be considered invalid if 3804d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * your activity is finished. The rationale is that once the activity that 3814d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * initiated printing is finished, the provided adapter may be in an inconsistent 3824d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * state as it may depend on the UI presented by the activity. 3834d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * </p> 3844d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * <p> 3854d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * The default print attributes are a hint to the system how the data is to 3864d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * be printed. For example, a photo editor may look at the photo aspect ratio 3874d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * to determine the default orientation and provide a hint whether the printing 3884d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * should be in portrait or landscape. The system will do a best effort to 3894d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * selected the hinted options in the print dialog, given the current printer 3904d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * supports them. 3914d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * </p> 39281f14b96899afa90330e2652acb629345acf17b1Svetoslav * <p> 39381f14b96899afa90330e2652acb629345acf17b1Svetoslav * <strong>Note:</strong> Calling this method will bring the print dialog and 39481f14b96899afa90330e2652acb629345acf17b1Svetoslav * the system will connect to the provided {@link PrintDocumentAdapter}. If a 39585a85a0ed775999533b14a415fd79b50fe63e6d2Svetoslav * configuration change occurs that you application does not handle, for example 39685a85a0ed775999533b14a415fd79b50fe63e6d2Svetoslav * a rotation change, the system will drop the connection to the adapter as the 39785a85a0ed775999533b14a415fd79b50fe63e6d2Svetoslav * activity has to be recreated and the old adapter may be invalid in this context, 39885a85a0ed775999533b14a415fd79b50fe63e6d2Svetoslav * hence a new adapter instance is required. As a consequence, if your activity 39985a85a0ed775999533b14a415fd79b50fe63e6d2Svetoslav * does not handle configuration changes (default behavior), you have to save the 40085a85a0ed775999533b14a415fd79b50fe63e6d2Svetoslav * state that you were printing and call this method again when your activity 40185a85a0ed775999533b14a415fd79b50fe63e6d2Svetoslav * is recreated. 40281f14b96899afa90330e2652acb629345acf17b1Svetoslav * </p> 4034d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * 4044d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * @param printJobName A name for the new print job which is shown to the user. 405a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * @param documentAdapter An adapter that emits the document to print. 4064d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * @param attributes The default print job attributes or <code>null</code>. 407d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov * @return The created print job on success or null on failure. 4084d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * @throws IllegalStateException If not called from an {@link Activity}. 4094d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * @throws IllegalArgumentException If the print job name is empty or the 4104d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * document adapter is null. 4114d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * 412fd90651cfcc7e2b75254666fd6861038b72fb4acSvetoslav * @see PrintJob 4134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 414a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public PrintJob print(String printJobName, PrintDocumentAdapter documentAdapter, 4154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov PrintAttributes attributes) { 4162235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 4172235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 4182235a1772fc3c72b5c1795310e221d613cae01daSvetoslav return null; 4192235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 4204d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov if (!(mContext instanceof Activity)) { 4214d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov throw new IllegalStateException("Can print only from an activity"); 4224d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov } 42388d199130d44c6bacb383a7757e782cf97483c68Svetoslav Ganov if (TextUtils.isEmpty(printJobName)) { 4244d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov throw new IllegalArgumentException("printJobName cannot be empty"); 4254d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov } 4264d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov if (documentAdapter == null) { 4274d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov throw new IllegalArgumentException("documentAdapter cannot be null"); 42888d199130d44c6bacb383a7757e782cf97483c68Svetoslav Ganov } 429858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov PrintDocumentAdapterDelegate delegate = new PrintDocumentAdapterDelegate( 4304d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov (Activity) mContext, documentAdapter); 4314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov try { 4327bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav Bundle result = mService.print(printJobName, delegate, 4337bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav attributes, mContext.getPackageName(), mAppId, mUserId); 4347bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav if (result != null) { 4357bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav PrintJobInfo printJob = result.getParcelable(EXTRA_PRINT_JOB); 4367bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav IntentSender intent = result.getParcelable(EXTRA_PRINT_DIALOG_INTENT); 4377bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav if (printJob == null || intent == null) { 4387bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav return null; 4397bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 4407bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav try { 4417bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav mContext.startIntentSender(intent, null, 0, 0, 0); 4427bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav return new PrintJob(printJob, this); 4437bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } catch (SendIntentException sie) { 4447bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav Log.e(LOG_TAG, "Couldn't start print job config activity.", sie); 4457bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 4464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } catch (RemoteException re) { 4484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov Log.e(LOG_TAG, "Error creating a print job", re); 4494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return null; 4514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 45344720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov /** 454860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov * Gets the list of enabled print services. 4552235a1772fc3c72b5c1795310e221d613cae01daSvetoslav * 456860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov * @return The enabled service list or an empty list. 457860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov * @hide 458860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov */ 459860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov public List<PrintServiceInfo> getEnabledPrintServices() { 4602235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 4612235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 4622235a1772fc3c72b5c1795310e221d613cae01daSvetoslav return Collections.emptyList(); 4632235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 464860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov try { 465860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov List<PrintServiceInfo> enabledServices = mService.getEnabledPrintServices(mUserId); 466860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov if (enabledServices != null) { 467860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov return enabledServices; 468860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov } 469860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov } catch (RemoteException re) { 470d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav Log.e(LOG_TAG, "Error getting the enabled print services", re); 471d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav } 472d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav return Collections.emptyList(); 473d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav } 474d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav 475d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav /** 476d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav * Gets the list of installed print services. 4772235a1772fc3c72b5c1795310e221d613cae01daSvetoslav * 478d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav * @return The installed service list or an empty list. 479d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav * @hide 480d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav */ 481d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav public List<PrintServiceInfo> getInstalledPrintServices() { 4822235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 4832235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 4842235a1772fc3c72b5c1795310e221d613cae01daSvetoslav return Collections.emptyList(); 4852235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 486d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav try { 487d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav List<PrintServiceInfo> installedServices = mService.getInstalledPrintServices(mUserId); 488d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav if (installedServices != null) { 489d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav return installedServices; 490d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav } 491d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav } catch (RemoteException re) { 492d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav Log.e(LOG_TAG, "Error getting the installed print services", re); 493860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov } 494860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov return Collections.emptyList(); 495860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov } 496860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov 497860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov /** 49844720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov * @hide 49944720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov */ 50044720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov public PrinterDiscoverySession createPrinterDiscoverySession() { 5012235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 5022235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 5032235a1772fc3c72b5c1795310e221d613cae01daSvetoslav return null; 5042235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 50544720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov return new PrinterDiscoverySession(mService, mContext, mUserId); 50644720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 50744720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov 508858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov private static final class PrintDocumentAdapterDelegate extends IPrintDocumentAdapter.Stub 509858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov implements ActivityLifecycleCallbacks { 51085b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov private final Object mLock = new Object(); 51185b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov 512a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private Activity mActivity; // Strong reference OK - cleared in destroy 5134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 514a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private PrintDocumentAdapter mDocumentAdapter; // Strong reference OK - cleared in destroy 5154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 516a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private Handler mHandler; // Strong reference OK - cleared in destroy 517858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov 518a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private IPrintDocumentAdapterObserver mObserver; // Strong reference OK - cleared in destroy 519db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 520a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private DestroyableCallback mPendingCallback; 521858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov 5224d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov public PrintDocumentAdapterDelegate(Activity activity, 523858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov PrintDocumentAdapter documentAdapter) { 5244d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov mActivity = activity; 525a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mDocumentAdapter = documentAdapter; 526858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov mHandler = new MyHandler(mActivity.getMainLooper()); 527858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov mActivity.getApplication().registerActivityLifecycleCallbacks(this); 528858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 529858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov 530858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov @Override 531858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov public void setObserver(IPrintDocumentAdapterObserver observer) { 532858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov final boolean destroyed; 533858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov synchronized (mLock) { 534a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mObserver = observer; 535a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav destroyed = isDestroyedLocked(); 536858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 537a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 5386552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav if (destroyed && observer != null) { 539858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov try { 540858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov observer.onDestroy(); 541858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } catch (RemoteException re) { 542858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov Log.e(LOG_TAG, "Error announcing destroyed state", re); 543858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 544858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 5454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 5464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 5474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 5484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void start() { 549db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov synchronized (mLock) { 550a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // If destroyed the handler is null. 551a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (!isDestroyedLocked()) { 552a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mHandler.obtainMessage(MyHandler.MSG_ON_START, 553a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mDocumentAdapter).sendToTarget(); 554db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov } 555db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov } 5564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 5574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 5584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 5596283608e0bd40548742839f5a8b02f7e5c9c5c7cSvetoslav public void layout(PrintAttributes oldAttributes, PrintAttributes newAttributes, 56085b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov ILayoutResultCallback callback, Bundle metadata, int sequence) { 561db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 562a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav ICancellationSignal cancellationTransport = CancellationSignal.createTransport(); 563a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav try { 564a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav callback.onLayoutStarted(cancellationTransport, sequence); 565a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } catch (RemoteException re) { 566a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // The spooler is dead - can't recover. 567a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "Error notifying for layout start", re); 568a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return; 569858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 570a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 571a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav synchronized (mLock) { 572a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // If destroyed the handler is null. 573a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (isDestroyedLocked()) { 574a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return; 575db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov } 576a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 577a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav CancellationSignal cancellationSignal = CancellationSignal.fromTransport( 578a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav cancellationTransport); 579a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 580a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav SomeArgs args = SomeArgs.obtain(); 581a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg1 = mDocumentAdapter; 582a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg2 = oldAttributes; 583a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg3 = newAttributes; 584a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg4 = cancellationSignal; 585a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg5 = new MyLayoutResultCallback(callback, sequence); 586a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg6 = metadata; 587a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 588a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mHandler.obtainMessage(MyHandler.MSG_ON_LAYOUT, args).sendToTarget(); 58985b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov } 5904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 5914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 5924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 59385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov public void write(PageRange[] pages, ParcelFileDescriptor fd, 594704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov IWriteResultCallback callback, int sequence) { 595db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 596a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav ICancellationSignal cancellationTransport = CancellationSignal.createTransport(); 597a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav try { 598a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav callback.onWriteStarted(cancellationTransport, sequence); 599a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } catch (RemoteException re) { 600a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // The spooler is dead - can't recover. 601a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "Error notifying for write start", re); 602a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return; 60385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov } 6044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 605db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov synchronized (mLock) { 606a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // If destroyed the handler is null. 607a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (isDestroyedLocked()) { 608db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov return; 609db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov } 610db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 611a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav CancellationSignal cancellationSignal = CancellationSignal.fromTransport( 612a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav cancellationTransport); 613db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 614a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav SomeArgs args = SomeArgs.obtain(); 615a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg1 = mDocumentAdapter; 616a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg2 = pages; 617a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg3 = fd; 618a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg4 = cancellationSignal; 619a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg5 = new MyWriteResultCallback(callback, fd, sequence); 620db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 621a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mHandler.obtainMessage(MyHandler.MSG_ON_WRITE, args).sendToTarget(); 622db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov } 6234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 6244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 625858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov @Override 626a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public void finish() { 627d270cb9264f762257d1aadbeba9c4b38866e171cSvetoslav synchronized (mLock) { 628a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // If destroyed the handler is null. 629a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (!isDestroyedLocked()) { 630a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mHandler.obtainMessage(MyHandler.MSG_ON_FINISH, 631a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mDocumentAdapter).sendToTarget(); 632a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 633d270cb9264f762257d1aadbeba9c4b38866e171cSvetoslav } 634d270cb9264f762257d1aadbeba9c4b38866e171cSvetoslav } 635d270cb9264f762257d1aadbeba9c4b38866e171cSvetoslav 636d270cb9264f762257d1aadbeba9c4b38866e171cSvetoslav @Override 637fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov public void kill(String reason) { 638fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov synchronized (mLock) { 639fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov // If destroyed the handler is null. 640fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov if (!isDestroyedLocked()) { 641fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov mHandler.obtainMessage(MyHandler.MSG_ON_KILL, 642fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov reason).sendToTarget(); 643fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov } 644fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov } 645fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov } 646fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov 647fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov @Override 648858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov public void onActivityPaused(Activity activity) { 649858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov /* do nothing */ 650858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 651858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov 652858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov @Override 653858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov public void onActivityCreated(Activity activity, Bundle savedInstanceState) { 654858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov /* do nothing */ 655858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 656858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov 657858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov @Override 658858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov public void onActivityStarted(Activity activity) { 659858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov /* do nothing */ 660858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 661858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov 662858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov @Override 663858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov public void onActivityResumed(Activity activity) { 664858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov /* do nothing */ 665858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 666858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov 667858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov @Override 668858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov public void onActivityStopped(Activity activity) { 669858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov /* do nothing */ 670858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 671858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov 672858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov @Override 673858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov public void onActivitySaveInstanceState(Activity activity, Bundle outState) { 674858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov /* do nothing */ 675858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 676858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov 677858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov @Override 678858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov public void onActivityDestroyed(Activity activity) { 679858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov // We really care only if the activity is being destroyed to 680858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov // notify the the print spooler so it can close the print dialog. 681858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov // Note the the spooler has a death recipient that observes if 682858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov // this process gets killed so we cover the case of onDestroy not 683858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov // being called due to this process being killed to reclaim memory. 684a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav IPrintDocumentAdapterObserver observer = null; 685858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov synchronized (mLock) { 686858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov if (activity == mActivity) { 687858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov observer = mObserver; 688a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav destroyLocked(); 689858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 690858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 691858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov if (observer != null) { 692858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov try { 693858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov observer.onDestroy(); 694858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } catch (RemoteException re) { 695858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov Log.e(LOG_TAG, "Error announcing destroyed state", re); 696858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 697858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 698858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 699858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov 700a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private boolean isDestroyedLocked() { 701a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return (mActivity == null); 7024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 7034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 704a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private void destroyLocked() { 705a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mActivity.getApplication().unregisterActivityLifecycleCallbacks( 706a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav PrintDocumentAdapterDelegate.this); 707858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov mActivity = null; 708a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 709a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mDocumentAdapter = null; 710a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 711a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // This method is only called from the main thread, so 712a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // clearing the messages guarantees that any time a 713a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // message is handled we are not in a destroyed state. 714a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mHandler.removeMessages(MyHandler.MSG_ON_START); 715a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mHandler.removeMessages(MyHandler.MSG_ON_LAYOUT); 716a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mHandler.removeMessages(MyHandler.MSG_ON_WRITE); 717a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mHandler.removeMessages(MyHandler.MSG_ON_FINISH); 7184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mHandler = null; 719db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 720a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mObserver = null; 721db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 722a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (mPendingCallback != null) { 723a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mPendingCallback.destroy(); 724a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mPendingCallback = null; 725db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov } 726db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov } 727db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 7284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final class MyHandler extends Handler { 729a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public static final int MSG_ON_START = 1; 730a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public static final int MSG_ON_LAYOUT = 2; 731a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public static final int MSG_ON_WRITE = 3; 732a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public static final int MSG_ON_FINISH = 4; 733fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov public static final int MSG_ON_KILL = 5; 7344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 7354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public MyHandler(Looper looper) { 7364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov super(looper, null, true); 7374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 7384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 7394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 7404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void handleMessage(Message message) { 7414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov switch (message.what) { 742a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav case MSG_ON_START: { 743a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (DEBUG) { 744a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.i(LOG_TAG, "onStart()"); 745858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 746a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 747a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav ((PrintDocumentAdapter) message.obj).onStart(); 748858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } break; 7494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 750a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav case MSG_ON_LAYOUT: { 751a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav SomeArgs args = (SomeArgs) message.obj; 752a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav PrintDocumentAdapter adapter = (PrintDocumentAdapter) args.arg1; 753a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav PrintAttributes oldAttributes = (PrintAttributes) args.arg2; 754a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav PrintAttributes newAttributes = (PrintAttributes) args.arg3; 755a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav CancellationSignal cancellation = (CancellationSignal) args.arg4; 756a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav LayoutResultCallback callback = (LayoutResultCallback) args.arg5; 757a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Bundle metadata = (Bundle) args.arg6; 758a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.recycle(); 759db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 760a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (DEBUG) { 761a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav StringBuilder builder = new StringBuilder(); 762a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav builder.append("PrintDocumentAdapter#onLayout() {\n"); 763a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav builder.append("\n oldAttributes:").append(oldAttributes); 764a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav builder.append("\n newAttributes:").append(newAttributes); 765a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav builder.append("\n preview:").append(metadata.getBoolean( 766a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav PrintDocumentAdapter.EXTRA_PRINT_PREVIEW)); 767a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav builder.append("\n}"); 768a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.i(LOG_TAG, builder.toString()); 769a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 77085b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov 771a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav adapter.onLayout(oldAttributes, newAttributes, cancellation, 772a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav callback, metadata); 773858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } break; 7744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 775a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav case MSG_ON_WRITE: { 776a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav SomeArgs args = (SomeArgs) message.obj; 777a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav PrintDocumentAdapter adapter = (PrintDocumentAdapter) args.arg1; 778a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav PageRange[] pages = (PageRange[]) args.arg2; 779a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav ParcelFileDescriptor fd = (ParcelFileDescriptor) args.arg3; 780a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav CancellationSignal cancellation = (CancellationSignal) args.arg4; 781a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav WriteResultCallback callback = (WriteResultCallback) args.arg5; 782a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.recycle(); 783db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 784a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (DEBUG) { 785a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav StringBuilder builder = new StringBuilder(); 786a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav builder.append("PrintDocumentAdapter#onWrite() {\n"); 787a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav builder.append("\n pages:").append(Arrays.toString(pages)); 788a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav builder.append("\n}"); 789a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.i(LOG_TAG, builder.toString()); 7904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 79185b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov 792a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav adapter.onWrite(pages, fd, cancellation, callback); 793858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } break; 7944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 795a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav case MSG_ON_FINISH: { 796db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov if (DEBUG) { 797a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.i(LOG_TAG, "onFinish()"); 798db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov } 799a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 800a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav ((PrintDocumentAdapter) message.obj).onFinish(); 801a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 802a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // Done printing, so destroy this instance as it 803a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // should not be used anymore. 804858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov synchronized (mLock) { 805a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav destroyLocked(); 806858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 807858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } break; 8084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 809fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov case MSG_ON_KILL: { 810fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov if (DEBUG) { 811fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov Log.i(LOG_TAG, "onKill()"); 812fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov } 813fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov 814fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov String reason = (String) message.obj; 815fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov throw new RuntimeException(reason); 816fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov } 817fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov 8184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov default: { 8194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov throw new IllegalArgumentException("Unknown message: " 8204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov + message.what); 8214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 8224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 8234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 8244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 82514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 826a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private interface DestroyableCallback { 827a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public void destroy(); 828a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 829a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 830a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private final class MyLayoutResultCallback extends LayoutResultCallback 831a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav implements DestroyableCallback { 83214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov private ILayoutResultCallback mCallback; 83314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov private final int mSequence; 83414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 83514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov public MyLayoutResultCallback(ILayoutResultCallback callback, 83614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov int sequence) { 83714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov mCallback = callback; 83814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov mSequence = sequence; 83914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 84014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 84114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov @Override 84214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov public void onLayoutFinished(PrintDocumentInfo info, boolean changed) { 84314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov final ILayoutResultCallback callback; 84414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov synchronized (mLock) { 84514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov callback = mCallback; 84614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 847a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 848a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // If the callback is null we are destroyed. 849a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (callback == null) { 850a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you " 851a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "finish the printing activity before print completion " 852a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "or did you invoke a callback after finish?"); 853a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return; 854a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 855a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 856a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav try { 857a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (info == null) { 858a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav throw new NullPointerException("document info cannot be null"); 859a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 860a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 86114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov try { 86214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov callback.onLayoutFinished(info, changed, mSequence); 86314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } catch (RemoteException re) { 86414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov Log.e(LOG_TAG, "Error calling onLayoutFinished", re); 86514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 866a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } finally { 867a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav destroy(); 86814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 86914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 87014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 87114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov @Override 87214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov public void onLayoutFailed(CharSequence error) { 87314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov final ILayoutResultCallback callback; 87414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov synchronized (mLock) { 87514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov callback = mCallback; 87614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 877a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 878a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // If the callback is null we are destroyed. 879a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (callback == null) { 880a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you " 881a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "finish the printing activity before print completion " 882a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "or did you invoke a callback after finish?"); 883a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return; 884a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 885a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 886a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav try { 887a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav callback.onLayoutFailed(error, mSequence); 888a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } catch (RemoteException re) { 889a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "Error calling onLayoutFailed", re); 890a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } finally { 891a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav destroy(); 89214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 89314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 89414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 89514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov @Override 89614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov public void onLayoutCancelled() { 897a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav final ILayoutResultCallback callback; 89814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov synchronized (mLock) { 899a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav callback = mCallback; 900a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 901a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 902a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // If the callback is null we are destroyed. 903a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (callback == null) { 904a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you " 905a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "finish the printing activity before print completion " 906a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "or did you invoke a callback after finish?"); 907a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return; 908a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 909a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 910a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav try { 911a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav callback.onLayoutCanceled(mSequence); 912a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } catch (RemoteException re) { 913a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "Error calling onLayoutFailed", re); 914a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } finally { 915a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav destroy(); 91614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 91714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 91814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 919a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav @Override 920a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public void destroy() { 921a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav synchronized (mLock) { 922a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mCallback = null; 923a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mPendingCallback = null; 924a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 92514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 92614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 92714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 928a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private final class MyWriteResultCallback extends WriteResultCallback 929a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav implements DestroyableCallback { 930d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov private ParcelFileDescriptor mFd; 93114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov private IWriteResultCallback mCallback; 932a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private final int mSequence; 93314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 93414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov public MyWriteResultCallback(IWriteResultCallback callback, 935d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov ParcelFileDescriptor fd, int sequence) { 93614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov mFd = fd; 93714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov mSequence = sequence; 93814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov mCallback = callback; 93914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 94014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 94114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov @Override 94214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov public void onWriteFinished(PageRange[] pages) { 94314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov final IWriteResultCallback callback; 94414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov synchronized (mLock) { 94514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov callback = mCallback; 94614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 947a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 948a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // If the callback is null we are destroyed. 949a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (callback == null) { 950a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you " 951a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "finish the printing activity before print completion " 952a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "or did you invoke a callback after finish?"); 953a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return; 95414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 955a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 956a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav try { 957a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (pages == null) { 958a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav throw new IllegalArgumentException("pages cannot be null"); 959a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 960a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (pages.length == 0) { 961a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav throw new IllegalArgumentException("pages cannot be empty"); 962a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 963a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 96414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov try { 96514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov callback.onWriteFinished(pages, mSequence); 96614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } catch (RemoteException re) { 96714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov Log.e(LOG_TAG, "Error calling onWriteFinished", re); 96814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 969a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } finally { 970a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav destroy(); 97114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 97214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 97314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 97414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov @Override 97514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov public void onWriteFailed(CharSequence error) { 97614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov final IWriteResultCallback callback; 97714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov synchronized (mLock) { 97814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov callback = mCallback; 97914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 980a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 981a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // If the callback is null we are destroyed. 982a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (callback == null) { 983a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you " 984a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "finish the printing activity before print completion " 985a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "or did you invoke a callback after finish?"); 986a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return; 987a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 988a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 989a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav try { 990a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav callback.onWriteFailed(error, mSequence); 991a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } catch (RemoteException re) { 992a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "Error calling onWriteFailed", re); 993a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } finally { 994a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav destroy(); 99514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 99614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 99714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 99814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov @Override 99914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov public void onWriteCancelled() { 1000a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav final IWriteResultCallback callback; 100114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov synchronized (mLock) { 1002a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav callback = mCallback; 1003a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 1004a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 1005a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // If the callback is null we are destroyed. 1006a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (callback == null) { 1007a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you " 1008a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "finish the printing activity before print completion " 1009a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "or did you invoke a callback after finish?"); 1010a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return; 1011a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 1012a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 1013a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav try { 1014a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav callback.onWriteCanceled(mSequence); 1015a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } catch (RemoteException re) { 1016a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "Error calling onWriteCanceled", re); 1017a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } finally { 1018a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav destroy(); 101914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 102014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 102114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 1022a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav @Override 1023a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public void destroy() { 1024a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav synchronized (mLock) { 1025a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav IoUtils.closeQuietly(mFd); 1026a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mCallback = null; 1027a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mFd = null; 1028a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mPendingCallback = null; 1029a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 103014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 103114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 10324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1033704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 1034704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov private static final class PrintJobStateChangeListenerWrapper extends 1035704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov IPrintJobStateChangeListener.Stub { 1036704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov private final WeakReference<PrintJobStateChangeListener> mWeakListener; 1037a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov private final WeakReference<Handler> mWeakHandler; 1038704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 1039a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov public PrintJobStateChangeListenerWrapper(PrintJobStateChangeListener listener, 1040a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov Handler handler) { 1041704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov mWeakListener = new WeakReference<PrintJobStateChangeListener>(listener); 1042a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov mWeakHandler = new WeakReference<Handler>(handler); 1043704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 1044704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 1045704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov @Override 1046704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov public void onPrintJobStateChanged(PrintJobId printJobId) { 1047a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov Handler handler = mWeakHandler.get(); 1048704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov PrintJobStateChangeListener listener = mWeakListener.get(); 1049a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov if (handler != null && listener != null) { 1050a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov SomeArgs args = SomeArgs.obtain(); 1051d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov args.arg1 = this; 1052a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov args.arg2 = printJobId; 1053a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov handler.obtainMessage(MSG_NOTIFY_PRINT_JOB_STATE_CHANGED, 1054a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov args).sendToTarget(); 1055704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 1056704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 1057a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov 1058d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov public void destroy() { 1059d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov mWeakListener.clear(); 1060d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov } 1061d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov 1062d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov public PrintJobStateChangeListener getListener() { 1063d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov return mWeakListener.get(); 1064d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov } 1065d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov } 10664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov} 1067