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 19c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmannimport android.annotation.NonNull; 20c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmannimport android.annotation.Nullable; 2198af2e4fec8c417f4a674a99f4b40f6f248d6a83Jeff Sharkeyimport android.annotation.RequiresFeature; 226870033d374a15fd212675d570a2877c28f1cbf0Philip P. Moltmannimport android.annotation.RequiresPermission; 237e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmannimport android.annotation.SystemApi; 24d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkeyimport android.annotation.SystemService; 25858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganovimport android.app.Activity; 26858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganovimport android.app.Application.ActivityLifecycleCallbacks; 2766c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmannimport android.content.ComponentName; 284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.Context; 294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.IntentSender; 304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.IntentSender.SendIntentException; 3198af2e4fec8c417f4a674a99f4b40f6f248d6a83Jeff Sharkeyimport android.content.pm.PackageManager; 32bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmannimport android.graphics.drawable.Icon; 336283608e0bd40548742839f5a8b02f7e5c9c5c7cSvetoslavimport android.os.Bundle; 344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.CancellationSignal; 354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Handler; 36a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.os.ICancellationSignal; 374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Looper; 384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Message; 394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.ParcelFileDescriptor; 404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.RemoteException; 41a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.PrintDocumentAdapter.LayoutResultCallback; 42a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.PrintDocumentAdapter.WriteResultCallback; 43860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganovimport android.printservice.PrintServiceInfo; 449dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.printservice.recommendation.IRecommendationsChangeListener; 459dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport android.printservice.recommendation.RecommendationInfo; 4688d199130d44c6bacb383a7757e782cf97483c68Svetoslav Ganovimport android.text.TextUtils; 47704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganovimport android.util.ArrayMap; 484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.util.Log; 494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport com.android.internal.os.SomeArgs; 519dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmannimport com.android.internal.util.Preconditions; 527e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann 534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport libcore.io.IoUtils; 544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.lang.ref.WeakReference; 564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.ArrayList; 57a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport java.util.Arrays; 584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.Collections; 594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.List; 60704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganovimport java.util.Map; 614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/** 634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * System level service for accessing the printing capabilities of the platform. 64a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * 654d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * <h3>Print mechanics</h3> 664d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * <p> 674d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * The key idea behind printing on the platform is that the content to be printed 684d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * should be laid out for the currently selected print options resulting in an 694d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * optimized output and higher user satisfaction. To achieve this goal the platform 704d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * declares a contract that the printing application has to follow which is defined 714d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * by the {@link PrintDocumentAdapter} class. At a higher level the contract is that 724d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * when the user selects some options from the print UI that may affect the way 734d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * content is laid out, for example page size, the application receives a callback 744d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * allowing it to layout the content to better fit these new constraints. After a 754d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * layout pass the system may ask the application to render one or more pages one 764d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * or more times. For example, an application may produce a single column list for 774d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * smaller page sizes and a multi-column table for larger page sizes. 784d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * </p> 794d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * <h3>Print jobs</h3> 804d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * <p> 814d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * Print jobs are started by calling the {@link #print(String, PrintDocumentAdapter, 824d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * PrintAttributes)} from an activity which results in bringing up the system print 834d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * UI. Once the print UI is up, when the user changes a selected print option that 844d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * affects the way content is laid out the system starts to interact with the 854d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * application following the mechanics described the section above. 864d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * </p> 874d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * <p> 884d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * Print jobs can be in {@link PrintJobInfo#STATE_CREATED created}, {@link 894d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * PrintJobInfo#STATE_QUEUED queued}, {@link PrintJobInfo#STATE_STARTED started}, 904d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * {@link PrintJobInfo#STATE_BLOCKED blocked}, {@link PrintJobInfo#STATE_COMPLETED 914d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * completed}, {@link PrintJobInfo#STATE_FAILED failed}, and {@link 924d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * PrintJobInfo#STATE_CANCELED canceled} state. Print jobs are stored in dedicated 934d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * system spooler until they are handled which is they are cancelled or completed. 944d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * Active print jobs, ones that are not cancelled or completed, are considered failed 954d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * if the device reboots as the new boot may be after a very long time. The user may 964d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * choose to restart such print jobs. Once a print job is queued all relevant content 974d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * is stored in the system spooler and its lifecycle becomes detached from this of 984d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * the application that created it. 994d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * </p> 1004d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * <p> 1014d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * An applications can query the print spooler for current print jobs it created 1024d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * but not print jobs created by other applications. 1034d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * </p> 1044d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * 1054d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * @see PrintJob 1064d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * @see PrintJobInfo 1074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 108d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkey@SystemService(Context.PRINT_SERVICE) 10998af2e4fec8c417f4a674a99f4b40f6f248d6a83Jeff Sharkey@RequiresFeature(PackageManager.FEATURE_PRINTING) 1104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovpublic final class PrintManager { 1114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private static final String LOG_TAG = "PrintManager"; 1134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 11415cbc8a03250eafdf947cd8ad4e77f34444d5ba4Svetoslav private static final boolean DEBUG = false; 115db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 1167bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav private static final int MSG_NOTIFY_PRINT_JOB_STATE_CHANGED = 1; 11766c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann 11866c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann /** 11966c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * Package name of print spooler. 12066c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * 12166c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * @hide 12266c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann */ 12366c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann public static final String PRINT_SPOOLER_PACKAGE_NAME = "com.android.printspooler"; 12466c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann 12566c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann /** 12666c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * Select enabled services. 12766c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * </p> 12866c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * @see #getPrintServices 12966c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * @hide 13066c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann */ 1317e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann @SystemApi 13266c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann public static final int ENABLED_SERVICES = 1 << 0; 13366c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann 13466c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann /** 13566c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * Select disabled services. 13666c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * </p> 13766c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * @see #getPrintServices 13866c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * @hide 13966c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann */ 14066c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann public static final int DISABLED_SERVICES = 1 << 1; 14166c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann 14266c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann /** 14366c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * Select all services. 14466c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * </p> 14566c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * @see #getPrintServices 14666c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * @hide 14766c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann */ 14866c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann public static final int ALL_SERVICES = ENABLED_SERVICES | DISABLED_SERVICES; 1497bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 1507bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav /** 1517bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * The action for launching the print dialog activity. 1527bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * 1537bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * @hide 1547bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav */ 1557bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final String ACTION_PRINT_DIALOG = "android.print.PRINT_DIALOG"; 1567bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 1577bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav /** 1587bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * Extra with the intent for starting the print dialog. 1597bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * <p> 1607bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * <strong>Type:</strong> {@link android.content.IntentSender} 1617bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * </p> 1627bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * 1637bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * @hide 1647bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav */ 1657bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final String EXTRA_PRINT_DIALOG_INTENT = 1667bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav "android.print.intent.extra.EXTRA_PRINT_DIALOG_INTENT"; 1677bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 1687bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav /** 1697bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * Extra with a print job. 1707bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * <p> 1717bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * <strong>Type:</strong> {@link android.print.PrintJobInfo} 1727bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * </p> 1737bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * 1747bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * @hide 1757bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav */ 1767bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final String EXTRA_PRINT_JOB = 1777bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav "android.print.intent.extra.EXTRA_PRINT_JOB"; 1787bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav 1797bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav /** 1807bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * Extra with the print document adapter to be printed. 1817bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * <p> 1827bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * <strong>Type:</strong> {@link android.print.IPrintDocumentAdapter} 1837bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * </p> 1847bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * 1857bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav * @hide 1867bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav */ 1877bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public static final String EXTRA_PRINT_DOCUMENT_ADAPTER = 1887bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav "android.print.intent.extra.EXTRA_PRINT_DOCUMENT_ADAPTER"; 189a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov 1904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** @hide */ 1914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public static final int APP_ID_ANY = -2; 1924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final Context mContext; 1944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final IPrintManager mService; 1964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final int mUserId; 1984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final int mAppId; 2004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final Handler mHandler; 2024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 20366c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann private Map<PrintJobStateChangeListener, PrintJobStateChangeListenerWrapper> 20466c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann mPrintJobStateChangeListeners; 20566c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann private Map<PrintServicesChangeListener, PrintServicesChangeListenerWrapper> 20666c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann mPrintServicesChangeListeners; 2079dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann private Map<PrintServiceRecommendationsChangeListener, 2089dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann PrintServiceRecommendationsChangeListenerWrapper> 2099dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann mPrintServiceRecommendationsChangeListeners; 210704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 211704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov /** @hide */ 212704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov public interface PrintJobStateChangeListener { 213704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 214704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov /** 215704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * Callback notifying that a print job state changed. 2162235a1772fc3c72b5c1795310e221d613cae01daSvetoslav * 217704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * @param printJobId The print job id. 218704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov */ 219a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov public void onPrintJobStateChanged(PrintJobId printJobId); 220704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 221704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 2227e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann /** 2237e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann * Listen for changes to {@link #getPrintServices(int)}. 2247e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann * 2257e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann * @hide 2267e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann */ 2277e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann @SystemApi 22866c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann public interface PrintServicesChangeListener { 22966c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann 23066c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann /** 23166c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * Callback notifying that the print services changed. 23266c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann */ 2337e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann void onPrintServicesChanged(); 23466c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann } 23566c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann 2367e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann /** 2377e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann * Listen for changes to {@link #getPrintServiceRecommendations()}. 2387e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann * 2397e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann * @hide 2407e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann */ 2417e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann @SystemApi 2429dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann public interface PrintServiceRecommendationsChangeListener { 2439dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann 2449dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann /** 2459dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * Callback notifying that the print service recommendations changed. 2469dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann */ 2479dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann void onPrintServiceRecommendationsChanged(); 2489dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } 2499dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann 2504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 2514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Creates a new instance. 2522235a1772fc3c72b5c1795310e221d613cae01daSvetoslav * 2534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @param context The current context in which to operate. 2544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @param service The backing system service. 255c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * @param userId The user id in which to operate. 256c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * @param appId The application id in which to operate. 2574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @hide 2584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 2594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public PrintManager(Context context, IPrintManager service, int userId, int appId) { 2604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mContext = context; 2614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mService = service; 2624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mUserId = userId; 2634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mAppId = appId; 2644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mHandler = new Handler(context.getMainLooper(), null, false) { 2654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 2664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void handleMessage(Message message) { 267a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov switch (message.what) { 268a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov case MSG_NOTIFY_PRINT_JOB_STATE_CHANGED: { 269a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov SomeArgs args = (SomeArgs) message.obj; 270d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov PrintJobStateChangeListenerWrapper wrapper = 271d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov (PrintJobStateChangeListenerWrapper) args.arg1; 272d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov PrintJobStateChangeListener listener = wrapper.getListener(); 273d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov if (listener != null) { 274d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov PrintJobId printJobId = (PrintJobId) args.arg2; 275d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov listener.onPrintJobStateChanged(printJobId); 276d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov } 277a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov args.recycle(); 2787bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } break; 2794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov }; 2824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2844b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 2854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Creates an instance that can access all print jobs. 2862235a1772fc3c72b5c1795310e221d613cae01daSvetoslav * 2874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @param userId The user id for which to get all print jobs. 288a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov * @return An instance if the caller has the permission to access all print 289a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov * jobs, null otherwise. 2904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @hide 2914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 2924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public PrintManager getGlobalPrintManagerForUser(int userId) { 2932235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 2942235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 2952235a1772fc3c72b5c1795310e221d613cae01daSvetoslav return null; 2962235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 2974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return new PrintManager(mContext, mService, userId, APP_ID_ANY); 2984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 3002fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav PrintJobInfo getPrintJobInfo(PrintJobId printJobId) { 3014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov try { 302a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return mService.getPrintJobInfo(printJobId, mAppId, mUserId); 3034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } catch (RemoteException re) { 304f8880561e67e1da246970b49b14285efd4164ab1Jeff Sharkey throw re.rethrowFromSystemServer(); 3054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 3084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 309704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * Adds a listener for observing the state of print jobs. 3102235a1772fc3c72b5c1795310e221d613cae01daSvetoslav * 311704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * @param listener The listener to add. 312704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * @hide 313704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov */ 314704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov public void addPrintJobStateChangeListener(PrintJobStateChangeListener listener) { 3152235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 3162235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 3172235a1772fc3c72b5c1795310e221d613cae01daSvetoslav return; 3182235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 319704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (mPrintJobStateChangeListeners == null) { 3207e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann mPrintJobStateChangeListeners = new ArrayMap<>(); 321704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 322704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov PrintJobStateChangeListenerWrapper wrappedListener = 323a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov new PrintJobStateChangeListenerWrapper(listener, mHandler); 324704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov try { 325704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov mService.addPrintJobStateChangeListener(wrappedListener, mAppId, mUserId); 326704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov mPrintJobStateChangeListeners.put(listener, wrappedListener); 327704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } catch (RemoteException re) { 328f8880561e67e1da246970b49b14285efd4164ab1Jeff Sharkey throw re.rethrowFromSystemServer(); 329704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 330704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 331704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 332704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov /** 333704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * Removes a listener for observing the state of print jobs. 3342235a1772fc3c72b5c1795310e221d613cae01daSvetoslav * 335704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * @param listener The listener to remove. 336704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * @hide 337704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov */ 338704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov public void removePrintJobStateChangeListener(PrintJobStateChangeListener listener) { 3392235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 3402235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 3412235a1772fc3c72b5c1795310e221d613cae01daSvetoslav return; 3422235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 343704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (mPrintJobStateChangeListeners == null) { 344704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov return; 345704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 346704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov PrintJobStateChangeListenerWrapper wrappedListener = 347704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov mPrintJobStateChangeListeners.remove(listener); 348704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (wrappedListener == null) { 349704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov return; 350704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 351704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (mPrintJobStateChangeListeners.isEmpty()) { 352704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov mPrintJobStateChangeListeners = null; 353704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 354d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov wrappedListener.destroy(); 355704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov try { 356704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov mService.removePrintJobStateChangeListener(wrappedListener, mUserId); 357704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } catch (RemoteException re) { 358f8880561e67e1da246970b49b14285efd4164ab1Jeff Sharkey throw re.rethrowFromSystemServer(); 359704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 360704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 361704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 362704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov /** 363704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * Gets a print job given its id. 3642235a1772fc3c72b5c1795310e221d613cae01daSvetoslav * 365c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann * @param printJobId The id of the print job. 366704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * @return The print job list. 367704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * @see PrintJob 368704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov * @hide 369704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov */ 370704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov public PrintJob getPrintJob(PrintJobId printJobId) { 3712235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 3722235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 3732235a1772fc3c72b5c1795310e221d613cae01daSvetoslav return null; 3742235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 375704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov try { 376704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov PrintJobInfo printJob = mService.getPrintJobInfo(printJobId, mAppId, mUserId); 377704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (printJob != null) { 378704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov return new PrintJob(printJob, this); 379704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 380704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } catch (RemoteException re) { 381f8880561e67e1da246970b49b14285efd4164ab1Jeff Sharkey throw re.rethrowFromSystemServer(); 382704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 383704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov return null; 384704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 385704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 386704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov /** 387bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann * Get the custom icon for a printer. If the icon is not cached, the icon is 388bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann * requested asynchronously. Once it is available the printer is updated. 389bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann * 390bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann * @param printerId the id of the printer the icon should be loaded for 391bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann * @return the custom icon to be used for the printer or null if the icon is 392bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann * not yet available 3937e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann * @see android.print.PrinterInfo.Builder#setHasCustomPrinterIcon(boolean) 394bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann * @hide 395bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann */ 396bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann public Icon getCustomPrinterIcon(PrinterId printerId) { 397bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann if (mService == null) { 398bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann Log.w(LOG_TAG, "Feature android.software.print not available"); 399bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann return null; 400bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann } 401bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann try { 402bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann return mService.getCustomPrinterIcon(printerId, mUserId); 403bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann } catch (RemoteException re) { 404f8880561e67e1da246970b49b14285efd4164ab1Jeff Sharkey throw re.rethrowFromSystemServer(); 405bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann } 406bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann } 407bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann 408bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann /** 4094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Gets the print jobs for this application. 4102235a1772fc3c72b5c1795310e221d613cae01daSvetoslav * 4114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @return The print job list. 4124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @see PrintJob 4134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 414c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann public @NonNull List<PrintJob> getPrintJobs() { 4152235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 4162235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 4172235a1772fc3c72b5c1795310e221d613cae01daSvetoslav return Collections.emptyList(); 4182235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 4194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov try { 420a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov List<PrintJobInfo> printJobInfos = mService.getPrintJobInfos(mAppId, mUserId); 4214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (printJobInfos == null) { 4224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return Collections.emptyList(); 4234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov final int printJobCount = printJobInfos.size(); 4254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov List<PrintJob> printJobs = new ArrayList<PrintJob>(printJobCount); 4264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov for (int i = 0; i < printJobCount; i++) { 4274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov printJobs.add(new PrintJob(printJobInfos.get(i), this)); 4284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return printJobs; 4304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } catch (RemoteException re) { 431f8880561e67e1da246970b49b14285efd4164ab1Jeff Sharkey throw re.rethrowFromSystemServer(); 4324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 4352fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav void cancelPrintJob(PrintJobId printJobId) { 4362235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 4372235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 4382235a1772fc3c72b5c1795310e221d613cae01daSvetoslav return; 4392235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 4404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov try { 4414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mService.cancelPrintJob(printJobId, mAppId, mUserId); 4424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } catch (RemoteException re) { 443f8880561e67e1da246970b49b14285efd4164ab1Jeff Sharkey throw re.rethrowFromSystemServer(); 4444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 447704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov void restartPrintJob(PrintJobId printJobId) { 4482235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 4492235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 4502235a1772fc3c72b5c1795310e221d613cae01daSvetoslav return; 4512235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 452704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov try { 453704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov mService.restartPrintJob(printJobId, mAppId, mUserId); 454704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } catch (RemoteException re) { 455f8880561e67e1da246970b49b14285efd4164ab1Jeff Sharkey throw re.rethrowFromSystemServer(); 456704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 457704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 458704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 4594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 460a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov * Creates a print job for printing a {@link PrintDocumentAdapter} with 461a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov * default print attributes. 4624d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * <p> 4634d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * Calling this method brings the print UI allowing the user to customize 4644d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * the print job and returns a {@link PrintJob} object without waiting for the 4654d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * user to customize or confirm the print job. The returned print job instance 4664d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * is in a {@link PrintJobInfo#STATE_CREATED created} state. 4674d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * <p> 4684d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * This method can be called only from an {@link Activity}. The rationale is that 4694d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * printing from a service will create an inconsistent user experience as the print 4704d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * UI would appear without any context. 4714d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * </p> 4724d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * <p> 4734d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * Also the passed in {@link PrintDocumentAdapter} will be considered invalid if 4744d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * your activity is finished. The rationale is that once the activity that 4754d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * initiated printing is finished, the provided adapter may be in an inconsistent 4764d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * state as it may depend on the UI presented by the activity. 4774d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * </p> 4784d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * <p> 4794d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * The default print attributes are a hint to the system how the data is to 4804d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * be printed. For example, a photo editor may look at the photo aspect ratio 4814d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * to determine the default orientation and provide a hint whether the printing 4824d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * should be in portrait or landscape. The system will do a best effort to 4834d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * selected the hinted options in the print dialog, given the current printer 4844d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * supports them. 4854d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * </p> 48681f14b96899afa90330e2652acb629345acf17b1Svetoslav * <p> 48781f14b96899afa90330e2652acb629345acf17b1Svetoslav * <strong>Note:</strong> Calling this method will bring the print dialog and 48881f14b96899afa90330e2652acb629345acf17b1Svetoslav * the system will connect to the provided {@link PrintDocumentAdapter}. If a 48985a85a0ed775999533b14a415fd79b50fe63e6d2Svetoslav * configuration change occurs that you application does not handle, for example 49085a85a0ed775999533b14a415fd79b50fe63e6d2Svetoslav * a rotation change, the system will drop the connection to the adapter as the 49185a85a0ed775999533b14a415fd79b50fe63e6d2Svetoslav * activity has to be recreated and the old adapter may be invalid in this context, 49285a85a0ed775999533b14a415fd79b50fe63e6d2Svetoslav * hence a new adapter instance is required. As a consequence, if your activity 49385a85a0ed775999533b14a415fd79b50fe63e6d2Svetoslav * does not handle configuration changes (default behavior), you have to save the 49485a85a0ed775999533b14a415fd79b50fe63e6d2Svetoslav * state that you were printing and call this method again when your activity 49585a85a0ed775999533b14a415fd79b50fe63e6d2Svetoslav * is recreated. 49681f14b96899afa90330e2652acb629345acf17b1Svetoslav * </p> 4974d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * 4984d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * @param printJobName A name for the new print job which is shown to the user. 499a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * @param documentAdapter An adapter that emits the document to print. 5004d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * @param attributes The default print job attributes or <code>null</code>. 501d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov * @return The created print job on success or null on failure. 5024d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * @throws IllegalStateException If not called from an {@link Activity}. 5034d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * @throws IllegalArgumentException If the print job name is empty or the 5044d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * document adapter is null. 5054d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov * 506fd90651cfcc7e2b75254666fd6861038b72fb4acSvetoslav * @see PrintJob 5074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 508c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann public @NonNull PrintJob print(@NonNull String printJobName, 509c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann @NonNull PrintDocumentAdapter documentAdapter, 510c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann @Nullable PrintAttributes attributes) { 5112235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 5122235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 5132235a1772fc3c72b5c1795310e221d613cae01daSvetoslav return null; 5142235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 5154d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov if (!(mContext instanceof Activity)) { 5164d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov throw new IllegalStateException("Can print only from an activity"); 5174d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov } 51888d199130d44c6bacb383a7757e782cf97483c68Svetoslav Ganov if (TextUtils.isEmpty(printJobName)) { 5194d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov throw new IllegalArgumentException("printJobName cannot be empty"); 5204d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov } 5214d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov if (documentAdapter == null) { 5224d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov throw new IllegalArgumentException("documentAdapter cannot be null"); 52388d199130d44c6bacb383a7757e782cf97483c68Svetoslav Ganov } 524858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov PrintDocumentAdapterDelegate delegate = new PrintDocumentAdapterDelegate( 5254d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov (Activity) mContext, documentAdapter); 5264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov try { 5277bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav Bundle result = mService.print(printJobName, delegate, 5287bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav attributes, mContext.getPackageName(), mAppId, mUserId); 5297bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav if (result != null) { 5307bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav PrintJobInfo printJob = result.getParcelable(EXTRA_PRINT_JOB); 5317bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav IntentSender intent = result.getParcelable(EXTRA_PRINT_DIALOG_INTENT); 5327bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav if (printJob == null || intent == null) { 5337bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav return null; 5347bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 5357bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav try { 5367bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav mContext.startIntentSender(intent, null, 0, 0, 0); 5377bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav return new PrintJob(printJob, this); 5387bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } catch (SendIntentException sie) { 5397bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav Log.e(LOG_TAG, "Couldn't start print job config activity.", sie); 5407bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav } 5414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 5424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } catch (RemoteException re) { 543f8880561e67e1da246970b49b14285efd4164ab1Jeff Sharkey throw re.rethrowFromSystemServer(); 5444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 5454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return null; 5464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 5474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 54844720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov /** 54966c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * Listen for changes to the installed and enabled print services. 5502235a1772fc3c72b5c1795310e221d613cae01daSvetoslav * 55166c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * @param listener the listener to add 5527e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann * @param handler the handler the listener is called back on 55366c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * 55466c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * @see android.print.PrintManager#getPrintServices 5557e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann * 5567e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann * @hide 557860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov */ 5587e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann @SystemApi 5596870033d374a15fd212675d570a2877c28f1cbf0Philip P. Moltmann @RequiresPermission(android.Manifest.permission.READ_PRINT_SERVICES) 5607e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann public void addPrintServicesChangeListener(@NonNull PrintServicesChangeListener listener, 5617e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann @Nullable Handler handler) { 5629dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann Preconditions.checkNotNull(listener); 5639dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann 5647e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann if (handler == null) { 5657e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann handler = mHandler; 5667e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann } 5677e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann 5682235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 5692235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 57066c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann return; 5712235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 57266c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann if (mPrintServicesChangeListeners == null) { 5739dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann mPrintServicesChangeListeners = new ArrayMap<>(); 57466c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann } 57566c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann PrintServicesChangeListenerWrapper wrappedListener = 5767e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann new PrintServicesChangeListenerWrapper(listener, handler); 577860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov try { 57866c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann mService.addPrintServicesChangeListener(wrappedListener, mUserId); 57966c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann mPrintServicesChangeListeners.put(listener, wrappedListener); 580860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov } catch (RemoteException re) { 581f8880561e67e1da246970b49b14285efd4164ab1Jeff Sharkey throw re.rethrowFromSystemServer(); 582d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav } 583d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav } 584d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav 585d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav /** 58666c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * Stop listening for changes to the installed and enabled print services. 5872235a1772fc3c72b5c1795310e221d613cae01daSvetoslav * 58866c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * @param listener the listener to remove 58966c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * 59066c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * @see android.print.PrintManager#getPrintServices 5917e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann * 5927e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann * @hide 593d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav */ 5947e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann @SystemApi 5956870033d374a15fd212675d570a2877c28f1cbf0Philip P. Moltmann @RequiresPermission(android.Manifest.permission.READ_PRINT_SERVICES) 5967e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann public void removePrintServicesChangeListener(@NonNull PrintServicesChangeListener listener) { 5979dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann Preconditions.checkNotNull(listener); 5989dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann 5992235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 6002235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 60166c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann return; 60266c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann } 60366c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann if (mPrintServicesChangeListeners == null) { 60466c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann return; 6052235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 60666c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann PrintServicesChangeListenerWrapper wrappedListener = 60766c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann mPrintServicesChangeListeners.remove(listener); 60866c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann if (wrappedListener == null) { 60966c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann return; 61066c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann } 61166c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann if (mPrintServicesChangeListeners.isEmpty()) { 61266c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann mPrintServicesChangeListeners = null; 61366c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann } 61466c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann wrappedListener.destroy(); 615d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav try { 61666c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann mService.removePrintServicesChangeListener(wrappedListener, mUserId); 61766c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann } catch (RemoteException re) { 61866c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann Log.e(LOG_TAG, "Error removing print services change listener", re); 61966c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann } 62066c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann } 62166c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann 62266c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann /** 62366c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * Gets the list of print services, but does not register for updates. The user has to register 62466c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * for updates by itself, or use {@link PrintServicesLoader}. 62566c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * 62666c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * @param selectionFlags flags selecting which services to get. Either 62766c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * {@link #ENABLED_SERVICES},{@link #DISABLED_SERVICES}, or both. 62866c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * 6299dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * @return The print service list or an empty list. 63066c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * 6317e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann * @see #addPrintServicesChangeListener(PrintServicesChangeListener, Handler) 63266c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * @see #removePrintServicesChangeListener(PrintServicesChangeListener) 63366c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * 63466c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * @hide 63566c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann */ 6367e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann @SystemApi 6376870033d374a15fd212675d570a2877c28f1cbf0Philip P. Moltmann @RequiresPermission(android.Manifest.permission.READ_PRINT_SERVICES) 63866c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann public @NonNull List<PrintServiceInfo> getPrintServices(int selectionFlags) { 6399dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann Preconditions.checkFlagsArgument(selectionFlags, ALL_SERVICES); 6409dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann 64166c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann try { 64266c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann List<PrintServiceInfo> services = mService.getPrintServices(selectionFlags, mUserId); 64366c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann if (services != null) { 64466c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann return services; 645d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav } 646d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav } catch (RemoteException re) { 647f8880561e67e1da246970b49b14285efd4164ab1Jeff Sharkey throw re.rethrowFromSystemServer(); 648860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov } 649860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov return Collections.emptyList(); 650860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov } 651860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov 652860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov /** 6539dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * Listen for changes to the print service recommendations. 6549dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * 6559dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * @param listener the listener to add 6567e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann * @param handler the handler the listener is called back on 6579dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * 6589dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * @see android.print.PrintManager#getPrintServiceRecommendations 6597e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann * 6607e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann * @hide 6619dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann */ 6627e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann @SystemApi 6636870033d374a15fd212675d570a2877c28f1cbf0Philip P. Moltmann @RequiresPermission(android.Manifest.permission.READ_PRINT_SERVICE_RECOMMENDATIONS) 6647e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann public void addPrintServiceRecommendationsChangeListener( 6657e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann @NonNull PrintServiceRecommendationsChangeListener listener, 6667e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann @Nullable Handler handler) { 6679dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann Preconditions.checkNotNull(listener); 6689dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann 6697e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann if (handler == null) { 6707e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann handler = mHandler; 6717e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann } 6727e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann 6739dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann if (mService == null) { 6749dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann Log.w(LOG_TAG, "Feature android.software.print not available"); 6759dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann return; 6769dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } 6779dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann if (mPrintServiceRecommendationsChangeListeners == null) { 6789dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann mPrintServiceRecommendationsChangeListeners = new ArrayMap<>(); 6799dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } 6809dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann PrintServiceRecommendationsChangeListenerWrapper wrappedListener = 6817e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann new PrintServiceRecommendationsChangeListenerWrapper(listener, handler); 6829dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann try { 6839dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann mService.addPrintServiceRecommendationsChangeListener(wrappedListener, mUserId); 6849dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann mPrintServiceRecommendationsChangeListeners.put(listener, wrappedListener); 6859dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } catch (RemoteException re) { 6869dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann throw re.rethrowFromSystemServer(); 6879dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } 6889dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } 6899dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann 6909dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann /** 6919dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * Stop listening for changes to the print service recommendations. 6929dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * 6939dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * @param listener the listener to remove 6949dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * 6959dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * @see android.print.PrintManager#getPrintServiceRecommendations 6967e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann * 6977e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann * @hide 6989dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann */ 6997e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann @SystemApi 7006870033d374a15fd212675d570a2877c28f1cbf0Philip P. Moltmann @RequiresPermission(android.Manifest.permission.READ_PRINT_SERVICE_RECOMMENDATIONS) 7017e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann public void removePrintServiceRecommendationsChangeListener( 7029dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann @NonNull PrintServiceRecommendationsChangeListener listener) { 7039dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann Preconditions.checkNotNull(listener); 7049dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann 7059dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann if (mService == null) { 7069dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann Log.w(LOG_TAG, "Feature android.software.print not available"); 7079dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann return; 7089dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } 7099dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann if (mPrintServiceRecommendationsChangeListeners == null) { 7109dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann return; 7119dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } 7129dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann PrintServiceRecommendationsChangeListenerWrapper wrappedListener = 7139dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann mPrintServiceRecommendationsChangeListeners.remove(listener); 7149dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann if (wrappedListener == null) { 7159dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann return; 7169dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } 7179dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann if (mPrintServiceRecommendationsChangeListeners.isEmpty()) { 7189dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann mPrintServiceRecommendationsChangeListeners = null; 7199dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } 7209dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann wrappedListener.destroy(); 7219dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann try { 7229dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann mService.removePrintServiceRecommendationsChangeListener(wrappedListener, mUserId); 7239dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } catch (RemoteException re) { 7249dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann throw re.rethrowFromSystemServer(); 7259dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } 7269dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } 7279dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann 7289dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann /** 7299dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * Gets the list of print service recommendations, but does not register for updates. The user 7309dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * has to register for updates by itself, or use {@link PrintServiceRecommendationsLoader}. 7319dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * 7329dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * @return The print service recommendations list or an empty list. 7339dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * 7349dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * @see #addPrintServiceRecommendationsChangeListener 7359dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * @see #removePrintServiceRecommendationsChangeListener 7369dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * 7379dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * @hide 7389dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann */ 7397e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann @SystemApi 7406870033d374a15fd212675d570a2877c28f1cbf0Philip P. Moltmann @RequiresPermission(android.Manifest.permission.READ_PRINT_SERVICE_RECOMMENDATIONS) 7419dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann public @NonNull List<RecommendationInfo> getPrintServiceRecommendations() { 7429dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann try { 7439dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann List<RecommendationInfo> recommendations = 7449dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann mService.getPrintServiceRecommendations(mUserId); 7459dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann if (recommendations != null) { 7469dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann return recommendations; 7479dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } 7489dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } catch (RemoteException re) { 7499dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann throw re.rethrowFromSystemServer(); 7509dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } 7519dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann return Collections.emptyList(); 7529dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } 7539dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann 7549dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann /** 75544720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov * @hide 75644720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov */ 75744720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov public PrinterDiscoverySession createPrinterDiscoverySession() { 7582235a1772fc3c72b5c1795310e221d613cae01daSvetoslav if (mService == null) { 7592235a1772fc3c72b5c1795310e221d613cae01daSvetoslav Log.w(LOG_TAG, "Feature android.software.print not available"); 7602235a1772fc3c72b5c1795310e221d613cae01daSvetoslav return null; 7612235a1772fc3c72b5c1795310e221d613cae01daSvetoslav } 76244720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov return new PrinterDiscoverySession(mService, mContext, mUserId); 76344720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov } 76444720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov 76576d7e3ee70c4299b22b1a03505d2b4f108716c75Philip P. Moltmann /** 76666c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * Enable or disable a print service. 76766c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * 76866c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * @param service The service to enabled or disable 76966c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * @param isEnabled whether the service should be enabled or disabled 77066c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * 77166c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * @hide 77266c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann */ 77366c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann public void setPrintServiceEnabled(@NonNull ComponentName service, boolean isEnabled) { 77466c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann if (mService == null) { 77566c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann Log.w(LOG_TAG, "Feature android.software.print not available"); 77666c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann return; 77766c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann } 77866c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann try { 77966c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann mService.setPrintServiceEnabled(service, isEnabled, mUserId); 78066c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann } catch (RemoteException re) { 78166c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann Log.e(LOG_TAG, "Error enabling or disabling " + service, re); 78266c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann } 78366c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann } 78466c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann 78566c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann /** 78676d7e3ee70c4299b22b1a03505d2b4f108716c75Philip P. Moltmann * @hide 78776d7e3ee70c4299b22b1a03505d2b4f108716c75Philip P. Moltmann */ 78876d7e3ee70c4299b22b1a03505d2b4f108716c75Philip P. Moltmann public static final class PrintDocumentAdapterDelegate extends IPrintDocumentAdapter.Stub 789858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov implements ActivityLifecycleCallbacks { 79085b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov private final Object mLock = new Object(); 79185b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov 792a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private Activity mActivity; // Strong reference OK - cleared in destroy 7934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 794a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private PrintDocumentAdapter mDocumentAdapter; // Strong reference OK - cleared in destroy 7954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 796a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private Handler mHandler; // Strong reference OK - cleared in destroy 797858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov 798a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private IPrintDocumentAdapterObserver mObserver; // Strong reference OK - cleared in destroy 799db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 800a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private DestroyableCallback mPendingCallback; 801858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov 8024d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov public PrintDocumentAdapterDelegate(Activity activity, 803858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov PrintDocumentAdapter documentAdapter) { 804c863489e67ffaf8d74de24cf1634d9b9619a2f60Philip P. Moltmann if (activity.isFinishing()) { 805c863489e67ffaf8d74de24cf1634d9b9619a2f60Philip P. Moltmann // The activity is already dead hence the onActivityDestroyed callback won't be 806c863489e67ffaf8d74de24cf1634d9b9619a2f60Philip P. Moltmann // triggered. Hence it is not save to print in this situation. 807c863489e67ffaf8d74de24cf1634d9b9619a2f60Philip P. Moltmann throw new IllegalStateException("Cannot start printing for finishing activity"); 808c863489e67ffaf8d74de24cf1634d9b9619a2f60Philip P. Moltmann } 809c863489e67ffaf8d74de24cf1634d9b9619a2f60Philip P. Moltmann 8104d4c66dd38e940082e385b49a33f4022ab04c738Svetoslav Ganov mActivity = activity; 811a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mDocumentAdapter = documentAdapter; 812858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov mHandler = new MyHandler(mActivity.getMainLooper()); 813858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov mActivity.getApplication().registerActivityLifecycleCallbacks(this); 814858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 815858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov 816858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov @Override 817858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov public void setObserver(IPrintDocumentAdapterObserver observer) { 818858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov final boolean destroyed; 819858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov synchronized (mLock) { 820a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mObserver = observer; 821a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav destroyed = isDestroyedLocked(); 822858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 823a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 8246552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav if (destroyed && observer != null) { 825858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov try { 826858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov observer.onDestroy(); 827858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } catch (RemoteException re) { 828858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov Log.e(LOG_TAG, "Error announcing destroyed state", re); 829858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 830858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 8314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 8324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 8334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 8344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void start() { 835db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov synchronized (mLock) { 836a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // If destroyed the handler is null. 837a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (!isDestroyedLocked()) { 838a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mHandler.obtainMessage(MyHandler.MSG_ON_START, 839a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mDocumentAdapter).sendToTarget(); 840db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov } 841db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov } 8424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 8434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 8444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 8456283608e0bd40548742839f5a8b02f7e5c9c5c7cSvetoslav public void layout(PrintAttributes oldAttributes, PrintAttributes newAttributes, 84685b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov ILayoutResultCallback callback, Bundle metadata, int sequence) { 847db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 848a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav ICancellationSignal cancellationTransport = CancellationSignal.createTransport(); 849a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav try { 850a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav callback.onLayoutStarted(cancellationTransport, sequence); 851a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } catch (RemoteException re) { 852a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // The spooler is dead - can't recover. 853a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "Error notifying for layout start", re); 854a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return; 855858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 856a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 857a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav synchronized (mLock) { 858a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // If destroyed the handler is null. 859a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (isDestroyedLocked()) { 860a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return; 861db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov } 862a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 863a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav CancellationSignal cancellationSignal = CancellationSignal.fromTransport( 864a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav cancellationTransport); 865a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 866a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav SomeArgs args = SomeArgs.obtain(); 867a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg1 = mDocumentAdapter; 868a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg2 = oldAttributes; 869a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg3 = newAttributes; 870a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg4 = cancellationSignal; 871a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg5 = new MyLayoutResultCallback(callback, sequence); 872a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg6 = metadata; 873a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 874a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mHandler.obtainMessage(MyHandler.MSG_ON_LAYOUT, args).sendToTarget(); 87585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov } 8764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 8774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 8784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 87985b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov public void write(PageRange[] pages, ParcelFileDescriptor fd, 880704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov IWriteResultCallback callback, int sequence) { 881db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 882a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav ICancellationSignal cancellationTransport = CancellationSignal.createTransport(); 883a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav try { 884a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav callback.onWriteStarted(cancellationTransport, sequence); 885a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } catch (RemoteException re) { 886a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // The spooler is dead - can't recover. 887a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "Error notifying for write start", re); 888a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return; 88985b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov } 8904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 891db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov synchronized (mLock) { 892a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // If destroyed the handler is null. 893a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (isDestroyedLocked()) { 894db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov return; 895db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov } 896db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 897a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav CancellationSignal cancellationSignal = CancellationSignal.fromTransport( 898a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav cancellationTransport); 899db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 900a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav SomeArgs args = SomeArgs.obtain(); 901a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg1 = mDocumentAdapter; 902a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg2 = pages; 903a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg3 = fd; 904a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg4 = cancellationSignal; 905a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.arg5 = new MyWriteResultCallback(callback, fd, sequence); 906db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 907a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mHandler.obtainMessage(MyHandler.MSG_ON_WRITE, args).sendToTarget(); 908db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov } 9094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 9104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 911858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov @Override 912a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public void finish() { 913d270cb9264f762257d1aadbeba9c4b38866e171cSvetoslav synchronized (mLock) { 914a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // If destroyed the handler is null. 915a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (!isDestroyedLocked()) { 916a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mHandler.obtainMessage(MyHandler.MSG_ON_FINISH, 917a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mDocumentAdapter).sendToTarget(); 918a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 919d270cb9264f762257d1aadbeba9c4b38866e171cSvetoslav } 920d270cb9264f762257d1aadbeba9c4b38866e171cSvetoslav } 921d270cb9264f762257d1aadbeba9c4b38866e171cSvetoslav 922d270cb9264f762257d1aadbeba9c4b38866e171cSvetoslav @Override 923fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov public void kill(String reason) { 924fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov synchronized (mLock) { 925fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov // If destroyed the handler is null. 926fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov if (!isDestroyedLocked()) { 927fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov mHandler.obtainMessage(MyHandler.MSG_ON_KILL, 928fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov reason).sendToTarget(); 929fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov } 930fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov } 931fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov } 932fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov 933fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov @Override 934858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov public void onActivityPaused(Activity activity) { 935858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov /* do nothing */ 936858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 937858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov 938858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov @Override 939858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov public void onActivityCreated(Activity activity, Bundle savedInstanceState) { 940858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov /* do nothing */ 941858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 942858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov 943858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov @Override 944858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov public void onActivityStarted(Activity activity) { 945858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov /* do nothing */ 946858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 947858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov 948858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov @Override 949858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov public void onActivityResumed(Activity activity) { 950858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov /* do nothing */ 951858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 952858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov 953858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov @Override 954858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov public void onActivityStopped(Activity activity) { 955858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov /* do nothing */ 956858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 957858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov 958858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov @Override 959858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov public void onActivitySaveInstanceState(Activity activity, Bundle outState) { 960858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov /* do nothing */ 961858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 962858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov 963858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov @Override 964858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov public void onActivityDestroyed(Activity activity) { 965858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov // We really care only if the activity is being destroyed to 966858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov // notify the the print spooler so it can close the print dialog. 967858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov // Note the the spooler has a death recipient that observes if 968858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov // this process gets killed so we cover the case of onDestroy not 969858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov // being called due to this process being killed to reclaim memory. 970a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav IPrintDocumentAdapterObserver observer = null; 971858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov synchronized (mLock) { 972858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov if (activity == mActivity) { 973858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov observer = mObserver; 974a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav destroyLocked(); 975858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 976858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 977858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov if (observer != null) { 978858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov try { 979858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov observer.onDestroy(); 980858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } catch (RemoteException re) { 981858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov Log.e(LOG_TAG, "Error announcing destroyed state", re); 982858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 983858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 984858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 985858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov 986a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private boolean isDestroyedLocked() { 987a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return (mActivity == null); 9884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 9894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 990a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private void destroyLocked() { 991a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mActivity.getApplication().unregisterActivityLifecycleCallbacks( 992a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav PrintDocumentAdapterDelegate.this); 993858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov mActivity = null; 994a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 995a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mDocumentAdapter = null; 996a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 997a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // This method is only called from the main thread, so 998a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // clearing the messages guarantees that any time a 999a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // message is handled we are not in a destroyed state. 1000a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mHandler.removeMessages(MyHandler.MSG_ON_START); 1001a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mHandler.removeMessages(MyHandler.MSG_ON_LAYOUT); 1002a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mHandler.removeMessages(MyHandler.MSG_ON_WRITE); 1003a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mHandler.removeMessages(MyHandler.MSG_ON_FINISH); 10044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mHandler = null; 1005db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 1006a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mObserver = null; 1007db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 1008a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (mPendingCallback != null) { 1009a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mPendingCallback.destroy(); 1010a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mPendingCallback = null; 1011db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov } 1012db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov } 1013db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 10144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final class MyHandler extends Handler { 1015a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public static final int MSG_ON_START = 1; 1016a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public static final int MSG_ON_LAYOUT = 2; 1017a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public static final int MSG_ON_WRITE = 3; 1018a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public static final int MSG_ON_FINISH = 4; 1019fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov public static final int MSG_ON_KILL = 5; 10204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 10214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public MyHandler(Looper looper) { 10224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov super(looper, null, true); 10234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 10244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 10254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 10264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void handleMessage(Message message) { 10274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov switch (message.what) { 1028a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav case MSG_ON_START: { 1029a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (DEBUG) { 1030a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.i(LOG_TAG, "onStart()"); 1031858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 1032a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 1033a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav ((PrintDocumentAdapter) message.obj).onStart(); 1034858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } break; 10354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1036a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav case MSG_ON_LAYOUT: { 1037a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav SomeArgs args = (SomeArgs) message.obj; 1038a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav PrintDocumentAdapter adapter = (PrintDocumentAdapter) args.arg1; 1039a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav PrintAttributes oldAttributes = (PrintAttributes) args.arg2; 1040a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav PrintAttributes newAttributes = (PrintAttributes) args.arg3; 1041a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav CancellationSignal cancellation = (CancellationSignal) args.arg4; 1042a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav LayoutResultCallback callback = (LayoutResultCallback) args.arg5; 1043a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Bundle metadata = (Bundle) args.arg6; 1044a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.recycle(); 1045db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 1046a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (DEBUG) { 1047a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav StringBuilder builder = new StringBuilder(); 1048a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav builder.append("PrintDocumentAdapter#onLayout() {\n"); 1049a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav builder.append("\n oldAttributes:").append(oldAttributes); 1050a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav builder.append("\n newAttributes:").append(newAttributes); 1051a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav builder.append("\n preview:").append(metadata.getBoolean( 1052a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav PrintDocumentAdapter.EXTRA_PRINT_PREVIEW)); 1053a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav builder.append("\n}"); 1054a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.i(LOG_TAG, builder.toString()); 1055a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 105685b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov 1057a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav adapter.onLayout(oldAttributes, newAttributes, cancellation, 1058a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav callback, metadata); 1059858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } break; 10604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1061a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav case MSG_ON_WRITE: { 1062a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav SomeArgs args = (SomeArgs) message.obj; 1063a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav PrintDocumentAdapter adapter = (PrintDocumentAdapter) args.arg1; 1064a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav PageRange[] pages = (PageRange[]) args.arg2; 1065a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav ParcelFileDescriptor fd = (ParcelFileDescriptor) args.arg3; 1066a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav CancellationSignal cancellation = (CancellationSignal) args.arg4; 1067a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav WriteResultCallback callback = (WriteResultCallback) args.arg5; 1068a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav args.recycle(); 1069db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov 1070a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (DEBUG) { 1071a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav StringBuilder builder = new StringBuilder(); 1072a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav builder.append("PrintDocumentAdapter#onWrite() {\n"); 1073a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav builder.append("\n pages:").append(Arrays.toString(pages)); 1074a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav builder.append("\n}"); 1075a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.i(LOG_TAG, builder.toString()); 10764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 107785b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov 1078a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav adapter.onWrite(pages, fd, cancellation, callback); 1079858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } break; 10804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1081a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav case MSG_ON_FINISH: { 1082db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov if (DEBUG) { 1083a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.i(LOG_TAG, "onFinish()"); 1084db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov } 1085a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 1086a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav ((PrintDocumentAdapter) message.obj).onFinish(); 1087a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 1088a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // Done printing, so destroy this instance as it 1089a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // should not be used anymore. 1090858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov synchronized (mLock) { 1091a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav destroyLocked(); 1092858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } 1093858a1850e2e1c4516129d27ecdf54aaeade606caSvetoslav Ganov } break; 10944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1095fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov case MSG_ON_KILL: { 1096fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov if (DEBUG) { 1097fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov Log.i(LOG_TAG, "onKill()"); 1098fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov } 1099fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov 1100fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov String reason = (String) message.obj; 1101fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov throw new RuntimeException(reason); 1102fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov } 1103fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov 11044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov default: { 11054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov throw new IllegalArgumentException("Unknown message: " 11064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov + message.what); 11074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 11084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 11094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 11104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 111114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 1112a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private interface DestroyableCallback { 1113a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public void destroy(); 1114a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 1115a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 1116a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private final class MyLayoutResultCallback extends LayoutResultCallback 1117a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav implements DestroyableCallback { 111814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov private ILayoutResultCallback mCallback; 111914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov private final int mSequence; 112014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 112114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov public MyLayoutResultCallback(ILayoutResultCallback callback, 112214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov int sequence) { 112314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov mCallback = callback; 112414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov mSequence = sequence; 112514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 112614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 112714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov @Override 112814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov public void onLayoutFinished(PrintDocumentInfo info, boolean changed) { 112914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov final ILayoutResultCallback callback; 113014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov synchronized (mLock) { 113114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov callback = mCallback; 113214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 1133a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 1134a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // If the callback is null we are destroyed. 1135a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (callback == null) { 1136a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you " 1137a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "finish the printing activity before print completion " 1138a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "or did you invoke a callback after finish?"); 1139a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return; 1140a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 1141a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 1142a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav try { 1143a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (info == null) { 1144a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav throw new NullPointerException("document info cannot be null"); 1145a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 1146a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 114714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov try { 114814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov callback.onLayoutFinished(info, changed, mSequence); 114914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } catch (RemoteException re) { 115014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov Log.e(LOG_TAG, "Error calling onLayoutFinished", re); 115114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 1152a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } finally { 1153a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav destroy(); 115414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 115514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 115614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 115714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov @Override 115814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov public void onLayoutFailed(CharSequence error) { 115914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov final ILayoutResultCallback callback; 116014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov synchronized (mLock) { 116114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov callback = mCallback; 116214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 1163a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 1164a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // If the callback is null we are destroyed. 1165a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (callback == null) { 1166a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you " 1167a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "finish the printing activity before print completion " 1168a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "or did you invoke a callback after finish?"); 1169a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return; 1170a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 1171a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 1172a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav try { 1173a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav callback.onLayoutFailed(error, mSequence); 1174a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } catch (RemoteException re) { 1175a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "Error calling onLayoutFailed", re); 1176a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } finally { 1177a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav destroy(); 117814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 117914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 118014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 118114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov @Override 118214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov public void onLayoutCancelled() { 1183a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav final ILayoutResultCallback callback; 118414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov synchronized (mLock) { 1185a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav callback = mCallback; 1186a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 1187a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 1188a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // If the callback is null we are destroyed. 1189a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (callback == null) { 1190a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you " 1191a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "finish the printing activity before print completion " 1192a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "or did you invoke a callback after finish?"); 1193a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return; 1194a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 1195a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 1196a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav try { 1197a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav callback.onLayoutCanceled(mSequence); 1198a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } catch (RemoteException re) { 1199a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "Error calling onLayoutFailed", re); 1200a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } finally { 1201a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav destroy(); 120214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 120314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 120414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 1205a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav @Override 1206a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public void destroy() { 1207a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav synchronized (mLock) { 1208a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mCallback = null; 1209a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mPendingCallback = null; 1210a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 121114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 121214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 121314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 1214a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private final class MyWriteResultCallback extends WriteResultCallback 1215a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav implements DestroyableCallback { 1216d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov private ParcelFileDescriptor mFd; 121714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov private IWriteResultCallback mCallback; 1218a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav private final int mSequence; 121914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 122014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov public MyWriteResultCallback(IWriteResultCallback callback, 1221d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov ParcelFileDescriptor fd, int sequence) { 122214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov mFd = fd; 122314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov mSequence = sequence; 122414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov mCallback = callback; 122514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 122614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 122714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov @Override 122814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov public void onWriteFinished(PageRange[] pages) { 122914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov final IWriteResultCallback callback; 123014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov synchronized (mLock) { 123114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov callback = mCallback; 123214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 1233a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 1234a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // If the callback is null we are destroyed. 1235a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (callback == null) { 1236a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you " 1237a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "finish the printing activity before print completion " 1238a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "or did you invoke a callback after finish?"); 1239a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return; 124014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 1241a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 1242a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav try { 1243a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (pages == null) { 1244a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav throw new IllegalArgumentException("pages cannot be null"); 1245a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 1246a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (pages.length == 0) { 1247a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav throw new IllegalArgumentException("pages cannot be empty"); 1248a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 1249a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 125014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov try { 125114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov callback.onWriteFinished(pages, mSequence); 125214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } catch (RemoteException re) { 125314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov Log.e(LOG_TAG, "Error calling onWriteFinished", re); 125414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 1255a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } finally { 1256a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav destroy(); 125714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 125814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 125914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 126014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov @Override 126114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov public void onWriteFailed(CharSequence error) { 126214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov final IWriteResultCallback callback; 126314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov synchronized (mLock) { 126414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov callback = mCallback; 126514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 1266a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 1267a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // If the callback is null we are destroyed. 1268a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (callback == null) { 1269a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you " 1270a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "finish the printing activity before print completion " 1271a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "or did you invoke a callback after finish?"); 1272a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return; 1273a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 1274a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 1275a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav try { 1276a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav callback.onWriteFailed(error, mSequence); 1277a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } catch (RemoteException re) { 1278a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "Error calling onWriteFailed", re); 1279a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } finally { 1280a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav destroy(); 128114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 128214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 128314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 128414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov @Override 128514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov public void onWriteCancelled() { 1286a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav final IWriteResultCallback callback; 128714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov synchronized (mLock) { 1288a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav callback = mCallback; 1289a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 1290a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 1291a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav // If the callback is null we are destroyed. 1292a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav if (callback == null) { 1293a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you " 1294a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "finish the printing activity before print completion " 1295a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav + "or did you invoke a callback after finish?"); 1296a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav return; 1297a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 1298a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 1299a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav try { 1300a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav callback.onWriteCanceled(mSequence); 1301a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } catch (RemoteException re) { 1302a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav Log.e(LOG_TAG, "Error calling onWriteCanceled", re); 1303a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } finally { 1304a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav destroy(); 130514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 130614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 130714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov 1308a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav @Override 1309a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav public void destroy() { 1310a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav synchronized (mLock) { 1311a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav IoUtils.closeQuietly(mFd); 1312a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mCallback = null; 1313a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mFd = null; 1314a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav mPendingCallback = null; 1315a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav } 131614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 131714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov } 13184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1319704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 132076d7e3ee70c4299b22b1a03505d2b4f108716c75Philip P. Moltmann /** 132176d7e3ee70c4299b22b1a03505d2b4f108716c75Philip P. Moltmann * @hide 132276d7e3ee70c4299b22b1a03505d2b4f108716c75Philip P. Moltmann */ 132376d7e3ee70c4299b22b1a03505d2b4f108716c75Philip P. Moltmann public static final class PrintJobStateChangeListenerWrapper extends 1324704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov IPrintJobStateChangeListener.Stub { 1325704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov private final WeakReference<PrintJobStateChangeListener> mWeakListener; 1326a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov private final WeakReference<Handler> mWeakHandler; 1327704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 1328a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov public PrintJobStateChangeListenerWrapper(PrintJobStateChangeListener listener, 1329a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov Handler handler) { 1330704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov mWeakListener = new WeakReference<PrintJobStateChangeListener>(listener); 1331a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov mWeakHandler = new WeakReference<Handler>(handler); 1332704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 1333704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 1334704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov @Override 1335704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov public void onPrintJobStateChanged(PrintJobId printJobId) { 1336a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov Handler handler = mWeakHandler.get(); 1337704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov PrintJobStateChangeListener listener = mWeakListener.get(); 1338a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov if (handler != null && listener != null) { 1339a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov SomeArgs args = SomeArgs.obtain(); 1340d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov args.arg1 = this; 1341a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov args.arg2 = printJobId; 1342a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov handler.obtainMessage(MSG_NOTIFY_PRINT_JOB_STATE_CHANGED, 1343a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov args).sendToTarget(); 1344704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 1345704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 1346a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov 1347d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov public void destroy() { 1348d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov mWeakListener.clear(); 1349d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov } 1350d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov 1351d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov public PrintJobStateChangeListener getListener() { 1352d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov return mWeakListener.get(); 1353d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov } 1354d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov } 135566c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann 135666c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann /** 135766c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann * @hide 135866c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann */ 135966c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann public static final class PrintServicesChangeListenerWrapper extends 136066c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann IPrintServicesChangeListener.Stub { 136166c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann private final WeakReference<PrintServicesChangeListener> mWeakListener; 136266c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann private final WeakReference<Handler> mWeakHandler; 136366c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann 136466c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann public PrintServicesChangeListenerWrapper(PrintServicesChangeListener listener, 136566c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann Handler handler) { 136666c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann mWeakListener = new WeakReference<>(listener); 136766c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann mWeakHandler = new WeakReference<>(handler); 136866c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann } 136966c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann 137066c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann @Override 137166c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann public void onPrintServicesChanged() { 137266c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann Handler handler = mWeakHandler.get(); 137366c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann PrintServicesChangeListener listener = mWeakListener.get(); 137466c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann if (handler != null && listener != null) { 13757e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann handler.post(listener::onPrintServicesChanged); 137666c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann } 137766c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann } 137866c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann 137966c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann public void destroy() { 138066c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann mWeakListener.clear(); 138166c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann } 138266c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann } 13839dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann 13849dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann /** 13859dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann * @hide 13869dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann */ 13879dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann public static final class PrintServiceRecommendationsChangeListenerWrapper extends 13889dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann IRecommendationsChangeListener.Stub { 13899dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann private final WeakReference<PrintServiceRecommendationsChangeListener> mWeakListener; 13909dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann private final WeakReference<Handler> mWeakHandler; 13919dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann 13929dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann public PrintServiceRecommendationsChangeListenerWrapper( 13939dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann PrintServiceRecommendationsChangeListener listener, Handler handler) { 13949dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann mWeakListener = new WeakReference<>(listener); 13959dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann mWeakHandler = new WeakReference<>(handler); 13969dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } 13979dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann 13989dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann @Override 13999dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann public void onRecommendationsChanged() { 14009dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann Handler handler = mWeakHandler.get(); 14019dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann PrintServiceRecommendationsChangeListener listener = mWeakListener.get(); 14029dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann if (handler != null && listener != null) { 14037e01895e6972c0ebc552215b1207a519529af3fdPhilip P. Moltmann handler.post(listener::onPrintServiceRecommendationsChanged); 14049dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } 14059dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } 14069dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann 14079dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann public void destroy() { 14089dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann mWeakListener.clear(); 14099dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } 14109dcb86a48d73f399fb1b5c020005d76d350eeac2Philip P. Moltmann } 14114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov} 1412