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