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