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
194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.Context;
204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.IntentSender;
214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.IntentSender.SendIntentException;
226283608e0bd40548742839f5a8b02f7e5c9c5c7cSvetoslavimport android.os.Bundle;
234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.CancellationSignal;
244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Handler;
254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Looper;
264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Message;
274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.ParcelFileDescriptor;
284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.RemoteException;
29a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.PrintDocumentAdapter.LayoutResultCallback;
30a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.PrintDocumentAdapter.WriteResultCallback;
31860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganovimport android.printservice.PrintServiceInfo;
3288d199130d44c6bacb383a7757e782cf97483c68Svetoslav Ganovimport android.text.TextUtils;
33704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganovimport android.util.ArrayMap;
344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.util.Log;
354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport com.android.internal.os.SomeArgs;
374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport libcore.io.IoUtils;
394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.lang.ref.WeakReference;
414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.ArrayList;
424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.Collections;
434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.List;
44704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganovimport java.util.Map;
454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/**
474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * System level service for accessing the printing capabilities of the platform.
484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p>
494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * To obtain a handle to the print manager do the following:
504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p>
51a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov *
524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <pre>
534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * PrintManager printManager =
544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov *         (PrintManager) context.getSystemService(Context.PRINT_SERVICE);
554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </pre>
564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */
574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovpublic final class PrintManager {
584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private static final String LOG_TAG = "PrintManager";
604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
61db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov    private static final boolean DEBUG = false;
62db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
637bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav    private static final int MSG_NOTIFY_PRINT_JOB_STATE_CHANGED = 1;
647bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav
657bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav    /**
667bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     * The action for launching the print dialog activity.
677bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     *
687bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     * @hide
697bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     */
707bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav    public static final String ACTION_PRINT_DIALOG = "android.print.PRINT_DIALOG";
717bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav
727bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav    /**
737bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     * Extra with the intent for starting the print dialog.
747bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     * <p>
757bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     * <strong>Type:</strong> {@link android.content.IntentSender}
767bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     * </p>
777bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     *
787bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     * @hide
797bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     */
807bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav    public static final String EXTRA_PRINT_DIALOG_INTENT =
817bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            "android.print.intent.extra.EXTRA_PRINT_DIALOG_INTENT";
827bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav
837bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav    /**
847bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     * Extra with a print job.
857bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     * <p>
867bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     * <strong>Type:</strong> {@link android.print.PrintJobInfo}
877bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     * </p>
887bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     *
897bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     * @hide
907bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     */
917bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav    public static final String EXTRA_PRINT_JOB =
927bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            "android.print.intent.extra.EXTRA_PRINT_JOB";
937bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav
947bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav    /**
957bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     * Extra with the print document adapter to be printed.
967bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     * <p>
977bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     * <strong>Type:</strong> {@link android.print.IPrintDocumentAdapter}
987bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     * </p>
997bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     *
1007bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     * @hide
1017bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav     */
1027bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav    public static final String EXTRA_PRINT_DOCUMENT_ADAPTER =
1037bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            "android.print.intent.extra.EXTRA_PRINT_DOCUMENT_ADAPTER";
104a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov
1054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /** @hide */
1064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public static final int APP_ID_ANY = -2;
1074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private final Context mContext;
1094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private final IPrintManager mService;
1114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private final int mUserId;
1134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private final int mAppId;
1154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private final Handler mHandler;
1174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
118704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov    private Map<PrintJobStateChangeListener, PrintJobStateChangeListenerWrapper> mPrintJobStateChangeListeners;
119704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov
120704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov    /** @hide */
121704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov    public interface PrintJobStateChangeListener {
122704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov
123704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        /**
124704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov         * Callback notifying that a print job state changed.
125a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov         *
126704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov         * @param printJobId The print job id.
127704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov         */
128a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        public void onPrintJobStateChanged(PrintJobId printJobId);
129704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov    }
130704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov
1314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
1324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Creates a new instance.
133a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov     *
1344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @param context The current context in which to operate.
1354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @param service The backing system service.
1364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @hide
1374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
1384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public PrintManager(Context context, IPrintManager service, int userId, int appId) {
1394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mContext = context;
1404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mService = service;
1414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mUserId = userId;
1424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mAppId = appId;
1434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mHandler = new Handler(context.getMainLooper(), null, false) {
1444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            @Override
1454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            public void handleMessage(Message message) {
146a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                switch (message.what) {
147a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                    case MSG_NOTIFY_PRINT_JOB_STATE_CHANGED: {
148a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                        SomeArgs args = (SomeArgs) message.obj;
149d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov                        PrintJobStateChangeListenerWrapper wrapper =
150d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov                                (PrintJobStateChangeListenerWrapper) args.arg1;
151d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov                        PrintJobStateChangeListener listener = wrapper.getListener();
152d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov                        if (listener != null) {
153d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov                            PrintJobId printJobId = (PrintJobId) args.arg2;
154d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov                            listener.onPrintJobStateChanged(printJobId);
155d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov                        }
156a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                        args.recycle();
1577bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                    } break;
1584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                }
1594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
1604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        };
1614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
1624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
1644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Creates an instance that can access all print jobs.
165a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov     *
1664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @param userId The user id for which to get all print jobs.
167a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov     * @return An instance if the caller has the permission to access all print
168a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov     *         jobs, null otherwise.
1694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @hide
1704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
1714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public PrintManager getGlobalPrintManagerForUser(int userId) {
1724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return new PrintManager(mContext, mService, userId, APP_ID_ANY);
1734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
1744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1752fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    PrintJobInfo getPrintJobInfo(PrintJobId printJobId) {
1764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        try {
177a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            return mService.getPrintJobInfo(printJobId, mAppId, mUserId);
1784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        } catch (RemoteException re) {
179a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            Log.e(LOG_TAG, "Error getting a print job info:" + printJobId, re);
1804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
1814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return null;
1824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
1834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1844b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
185704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov     * Adds a listener for observing the state of print jobs.
186a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov     *
187704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov     * @param listener The listener to add.
188704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov     * @hide
189704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov     */
190704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov    public void addPrintJobStateChangeListener(PrintJobStateChangeListener listener) {
191704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        if (mPrintJobStateChangeListeners == null) {
192704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            mPrintJobStateChangeListeners = new ArrayMap<PrintJobStateChangeListener,
193704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                    PrintJobStateChangeListenerWrapper>();
194704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        }
195704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        PrintJobStateChangeListenerWrapper wrappedListener =
196a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                new PrintJobStateChangeListenerWrapper(listener, mHandler);
197704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        try {
198704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            mService.addPrintJobStateChangeListener(wrappedListener, mAppId, mUserId);
199704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            mPrintJobStateChangeListeners.put(listener, wrappedListener);
200704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        } catch (RemoteException re) {
201704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            Log.e(LOG_TAG, "Error adding print job state change listener", re);
202704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        }
203704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov    }
204704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov
205704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov    /**
206704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov     * Removes a listener for observing the state of print jobs.
207a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov     *
208704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov     * @param listener The listener to remove.
209704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov     * @hide
210704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov     */
211704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov    public void removePrintJobStateChangeListener(PrintJobStateChangeListener listener) {
212704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        if (mPrintJobStateChangeListeners == null) {
213704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            return;
214704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        }
215704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        PrintJobStateChangeListenerWrapper wrappedListener =
216704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                mPrintJobStateChangeListeners.remove(listener);
217704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        if (wrappedListener == null) {
218704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            return;
219704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        }
220704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        if (mPrintJobStateChangeListeners.isEmpty()) {
221704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            mPrintJobStateChangeListeners = null;
222704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        }
223d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov        wrappedListener.destroy();
224704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        try {
225704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            mService.removePrintJobStateChangeListener(wrappedListener, mUserId);
226704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        } catch (RemoteException re) {
227704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            Log.e(LOG_TAG, "Error removing print job state change listener", re);
228704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        }
229704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov    }
230704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov
231704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov    /**
232704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov     * Gets a print job given its id.
233a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov     *
234704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov     * @return The print job list.
235704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov     * @see PrintJob
236704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov     * @hide
237704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov     */
238704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov    public PrintJob getPrintJob(PrintJobId printJobId) {
239704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        try {
240704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            PrintJobInfo printJob = mService.getPrintJobInfo(printJobId, mAppId, mUserId);
241704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            if (printJob != null) {
242704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                return new PrintJob(printJob, this);
243704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            }
244704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        } catch (RemoteException re) {
245704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            Log.e(LOG_TAG, "Error getting print job", re);
246704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        }
247704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        return null;
248704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov    }
249704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov
250704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov    /**
2514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Gets the print jobs for this application.
252a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov     *
2534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @return The print job list.
2544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see PrintJob
2554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
2564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public List<PrintJob> getPrintJobs() {
2574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        try {
258a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            List<PrintJobInfo> printJobInfos = mService.getPrintJobInfos(mAppId, mUserId);
2594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (printJobInfos == null) {
2604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                return Collections.emptyList();
2614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
2624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            final int printJobCount = printJobInfos.size();
2634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            List<PrintJob> printJobs = new ArrayList<PrintJob>(printJobCount);
2644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            for (int i = 0; i < printJobCount; i++) {
2654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                printJobs.add(new PrintJob(printJobInfos.get(i), this));
2664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
2674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return printJobs;
2684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        } catch (RemoteException re) {
269a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            Log.e(LOG_TAG, "Error getting print jobs", re);
2704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
2714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return Collections.emptyList();
2724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
2734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2742fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    void cancelPrintJob(PrintJobId printJobId) {
2754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        try {
2764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mService.cancelPrintJob(printJobId, mAppId, mUserId);
2774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        } catch (RemoteException re) {
278a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            Log.e(LOG_TAG, "Error cancleing a print job: " + printJobId, re);
2794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
2804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
2814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
282704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov    void restartPrintJob(PrintJobId printJobId) {
283704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        try {
284704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            mService.restartPrintJob(printJobId, mAppId, mUserId);
285704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        } catch (RemoteException re) {
286704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            Log.e(LOG_TAG, "Error restarting a print job: " + printJobId, re);
287704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        }
288704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov    }
289704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov
2904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
291a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov     * Creates a print job for printing a {@link PrintDocumentAdapter} with
292a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov     * default print attributes.
293a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov     *
2944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @param printJobName A name for the new print job.
295a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov     * @param documentAdapter An adapter that emits the document to print.
2964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @param attributes The default print job attributes.
297d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov     * @return The created print job on success or null on failure.
298fd90651cfcc7e2b75254666fd6861038b72fb4acSvetoslav     * @see PrintJob
2994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
300a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    public PrintJob print(String printJobName, PrintDocumentAdapter documentAdapter,
3014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            PrintAttributes attributes) {
30288d199130d44c6bacb383a7757e782cf97483c68Svetoslav Ganov        if (TextUtils.isEmpty(printJobName)) {
30388d199130d44c6bacb383a7757e782cf97483c68Svetoslav Ganov            throw new IllegalArgumentException("priintJobName cannot be empty");
30488d199130d44c6bacb383a7757e782cf97483c68Svetoslav Ganov        }
305a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        PrintDocumentAdapterDelegate delegate = new PrintDocumentAdapterDelegate(documentAdapter,
3064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                mContext.getMainLooper());
3074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        try {
3087bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            Bundle result = mService.print(printJobName, delegate,
3097bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                    attributes, mContext.getPackageName(), mAppId, mUserId);
3107bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            if (result != null) {
3117bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                PrintJobInfo printJob = result.getParcelable(EXTRA_PRINT_JOB);
3127bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                IntentSender intent = result.getParcelable(EXTRA_PRINT_DIALOG_INTENT);
3137bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                if (printJob == null || intent == null) {
3147bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                    return null;
3157bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                }
3167bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                try {
3177bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                    mContext.startIntentSender(intent, null, 0, 0, 0);
3187bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                    return new PrintJob(printJob, this);
3197bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                } catch (SendIntentException sie) {
3207bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                    Log.e(LOG_TAG, "Couldn't start print job config activity.", sie);
3217bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav                }
3224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
3234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        } catch (RemoteException re) {
3244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            Log.e(LOG_TAG, "Error creating a print job", re);
3254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
3264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return null;
3274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
3284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
32944720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov    /**
330860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov     * Gets the list of enabled print services.
331a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov     *
332860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov     * @return The enabled service list or an empty list.
333860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov     * @hide
334860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov     */
335860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov    public List<PrintServiceInfo> getEnabledPrintServices() {
336860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov        try {
337860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov            List<PrintServiceInfo> enabledServices = mService.getEnabledPrintServices(mUserId);
338860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov            if (enabledServices != null) {
339860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov                return enabledServices;
340860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov            }
341860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov        } catch (RemoteException re) {
342d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav            Log.e(LOG_TAG, "Error getting the enabled print services", re);
343d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav        }
344d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav        return Collections.emptyList();
345d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav    }
346d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav
347d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav    /**
348d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav     * Gets the list of installed print services.
349a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov     *
350d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav     * @return The installed service list or an empty list.
351d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav     * @hide
352d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav     */
353d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav    public List<PrintServiceInfo> getInstalledPrintServices() {
354d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav        try {
355d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav            List<PrintServiceInfo> installedServices = mService.getInstalledPrintServices(mUserId);
356d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav            if (installedServices != null) {
357d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav                return installedServices;
358d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav            }
359d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav        } catch (RemoteException re) {
360d8dbc13b47bec3248a86a505a30af9d0474240dcSvetoslav            Log.e(LOG_TAG, "Error getting the installed print services", re);
361860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov        }
362860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov        return Collections.emptyList();
363860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov    }
364860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov
365860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov    /**
36644720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov     * @hide
36744720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov     */
36844720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov    public PrinterDiscoverySession createPrinterDiscoverySession() {
36944720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov        return new PrinterDiscoverySession(mService, mContext, mUserId);
37044720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov    }
37144720af55a8fdf991929983dad5d53c02851dd1eSvetoslav Ganov
372a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private static final class PrintDocumentAdapterDelegate extends IPrintDocumentAdapter.Stub {
37385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov
37485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov        private final Object mLock = new Object();
37585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov
37685b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov        private CancellationSignal mLayoutOrWriteCancellation;
37785b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov
378a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        private PrintDocumentAdapter mDocumentAdapter; // Strong reference OK -
379a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                                                       // cleared in finish()
3804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
381a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        private Handler mHandler; // Strong reference OK - cleared in finish()
3824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
383db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov        private LayoutSpec mLastLayoutSpec;
384db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
385db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov        private WriteSpec mLastWriteSpec;
386db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
387db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov        private boolean mStartReqeusted;
388db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov        private boolean mStarted;
389db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
390db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov        private boolean mFinishRequested;
391db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov        private boolean mFinished;
392db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
393a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public PrintDocumentAdapterDelegate(PrintDocumentAdapter documentAdapter, Looper looper) {
394a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            mDocumentAdapter = documentAdapter;
3954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mHandler = new MyHandler(looper);
3964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
3974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
3984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        @Override
3994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public void start() {
400db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            synchronized (mLock) {
401db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                // Started or finished - nothing to do.
402db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                if (mStartReqeusted || mFinishRequested) {
403db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                    return;
404db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                }
405db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
406db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                mStartReqeusted = true;
407db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
408db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                doPendingWorkLocked();
409db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            }
4104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
4114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
4124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        @Override
4136283608e0bd40548742839f5a8b02f7e5c9c5c7cSvetoslav        public void layout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
41485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                ILayoutResultCallback callback, Bundle metadata, int sequence) {
41585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            synchronized (mLock) {
416db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                // Start not called or finish called - nothing to do.
417db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                if (!mStartReqeusted || mFinishRequested) {
418db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                    return;
419db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                }
420db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
421db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                // Layout cancels write and overrides layout.
422db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                if (mLastWriteSpec != null) {
423db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                    IoUtils.closeQuietly(mLastWriteSpec.fd);
424db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                    mLastWriteSpec = null;
42585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                }
426db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
427db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                mLastLayoutSpec = new LayoutSpec();
428db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                mLastLayoutSpec.callback = callback;
429db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                mLastLayoutSpec.oldAttributes = oldAttributes;
430db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                mLastLayoutSpec.newAttributes = newAttributes;
431db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                mLastLayoutSpec.metadata = metadata;
432db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                mLastLayoutSpec.sequence = sequence;
433db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
434db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                // Cancel the previous cancellable operation.When the
435db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                // cancellation completes we will do the pending work.
436db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                if (cancelPreviousCancellableOperationLocked()) {
437db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                    return;
438db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                }
439db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
440db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                doPendingWorkLocked();
44185b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            }
4424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
4434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
4444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        @Override
44585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov        public void write(PageRange[] pages, ParcelFileDescriptor fd,
446704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                IWriteResultCallback callback, int sequence) {
44785b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            synchronized (mLock) {
448db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                // Start not called or finish called - nothing to do.
449db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                if (!mStartReqeusted || mFinishRequested) {
450db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                    return;
451db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                }
452db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
453db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                // Write cancels previous writes.
454db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                if (mLastWriteSpec != null) {
455db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                    IoUtils.closeQuietly(mLastWriteSpec.fd);
456db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                    mLastWriteSpec = null;
45785b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                }
458db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
459db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                mLastWriteSpec = new WriteSpec();
460db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                mLastWriteSpec.callback = callback;
461db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                mLastWriteSpec.pages = pages;
462db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                mLastWriteSpec.fd = fd;
463db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                mLastWriteSpec.sequence = sequence;
464db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
465db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                // Cancel the previous cancellable operation.When the
466db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                // cancellation completes we will do the pending work.
467db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                if (cancelPreviousCancellableOperationLocked()) {
468db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                    return;
469db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                }
470db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
471db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                doPendingWorkLocked();
47285b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            }
4734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
4744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
4754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        @Override
4764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public void finish() {
477db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            synchronized (mLock) {
478db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                // Start not called or finish called - nothing to do.
479db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                if (!mStartReqeusted || mFinishRequested) {
480db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                    return;
481db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                }
482db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
483db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                mFinishRequested = true;
484db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
485db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                // When the current write or layout complete we
486db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                // will do the pending work.
487db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                if (mLastLayoutSpec != null || mLastWriteSpec != null) {
488db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                    if (DEBUG) {
489db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                        Log.i(LOG_TAG, "Waiting for current operation");
490db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                    }
491db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                    return;
492db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                }
493db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
494db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                doPendingWorkLocked();
495db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            }
4964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
4974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
498a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        private boolean isFinished() {
499a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            return mDocumentAdapter == null;
5004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
5014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
502a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        private void doFinish() {
503a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            mDocumentAdapter = null;
5044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mHandler = null;
505db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            synchronized (mLock) {
506db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                mLayoutOrWriteCancellation = null;
507db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            }
508db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov        }
509db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
510db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov        private boolean cancelPreviousCancellableOperationLocked() {
511db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            if (mLayoutOrWriteCancellation != null) {
512db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                mLayoutOrWriteCancellation.cancel();
513db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                if (DEBUG) {
514db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                    Log.i(LOG_TAG, "Cancelling previous operation");
515db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                }
516db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                return true;
517db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            }
518db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            return false;
519db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov        }
520db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
521db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov        private void doPendingWorkLocked() {
522db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            if (mStartReqeusted && !mStarted) {
523db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                mStarted = true;
524db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                mHandler.sendEmptyMessage(MyHandler.MSG_START);
525db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            } else if (mLastLayoutSpec != null) {
526db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                mHandler.sendEmptyMessage(MyHandler.MSG_LAYOUT);
527db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            } else if (mLastWriteSpec != null) {
528db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                mHandler.sendEmptyMessage(MyHandler.MSG_WRITE);
529db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            } else if (mFinishRequested && !mFinished) {
530db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                mFinished = true;
531db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                mHandler.sendEmptyMessage(MyHandler.MSG_FINISH);
532db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            }
533db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov        }
534db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
535db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov        private class LayoutSpec {
536db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            ILayoutResultCallback callback;
537db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            PrintAttributes oldAttributes;
538db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            PrintAttributes newAttributes;
539db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            Bundle metadata;
540db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            int sequence;
541db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov        }
542db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
543db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov        private class WriteSpec {
544db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            IWriteResultCallback callback;
545db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            PageRange[] pages;
546db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            ParcelFileDescriptor fd;
547db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov            int sequence;
5484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
5494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
5504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        private final class MyHandler extends Handler {
551a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            public static final int MSG_START = 1;
552a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            public static final int MSG_LAYOUT = 2;
553a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            public static final int MSG_WRITE = 3;
554a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            public static final int MSG_FINISH = 4;
5554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
5564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            public MyHandler(Looper looper) {
5574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                super(looper, null, true);
5584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
5594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
5604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            @Override
5614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            public void handleMessage(Message message) {
562a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                if (isFinished()) {
563a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    return;
564a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                }
5654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                switch (message.what) {
566a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    case MSG_START: {
567a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                        mDocumentAdapter.onStart();
568a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                    }
569a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                        break;
5704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
571a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    case MSG_LAYOUT: {
572db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                        final CancellationSignal cancellation;
573db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                        final LayoutSpec layoutSpec;
574db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
57585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                        synchronized (mLock) {
576db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                            layoutSpec = mLastLayoutSpec;
577db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                            mLastLayoutSpec = null;
578db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                            cancellation = new CancellationSignal();
57985b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                            mLayoutOrWriteCancellation = cancellation;
580a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                        }
58185b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov
582db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                        if (layoutSpec != null) {
583db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                            if (DEBUG) {
584db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                                Log.i(LOG_TAG, "Performing layout");
585db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                            }
586db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                            mDocumentAdapter.onLayout(layoutSpec.oldAttributes,
587db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                                    layoutSpec.newAttributes, cancellation,
588db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                                    new MyLayoutResultCallback(layoutSpec.callback,
589db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                                            layoutSpec.sequence), layoutSpec.metadata);
590db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                        }
591a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                    }
592a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                        break;
5934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
594a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    case MSG_WRITE: {
595db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                        final CancellationSignal cancellation;
596db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                        final WriteSpec writeSpec;
597db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov
59885b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                        synchronized (mLock) {
599a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                            writeSpec = mLastWriteSpec;
600db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                            mLastWriteSpec = null;
601db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                            cancellation = new CancellationSignal();
60285b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                            mLayoutOrWriteCancellation = cancellation;
6034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                        }
60485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov
605db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                        if (writeSpec != null) {
606db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                            if (DEBUG) {
607db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                                Log.i(LOG_TAG, "Performing write");
608db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                            }
609db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                            mDocumentAdapter.onWrite(writeSpec.pages, writeSpec.fd,
610db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                                    cancellation, new MyWriteResultCallback(writeSpec.callback,
611db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                                            writeSpec.fd, writeSpec.sequence));
612db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                        }
613a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                    }
614a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                        break;
6154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
616a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    case MSG_FINISH: {
617db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                        if (DEBUG) {
618db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                            Log.i(LOG_TAG, "Performing finish");
619db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                        }
620a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                        mDocumentAdapter.onFinish();
621a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                        doFinish();
622a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                    }
623a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                        break;
6244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
6254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    default: {
6264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                        throw new IllegalArgumentException("Unknown message: "
6274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                                + message.what);
6284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    }
6294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                }
6304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
6314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
63214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov
63314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov        private final class MyLayoutResultCallback extends LayoutResultCallback {
63414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            private ILayoutResultCallback mCallback;
63514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            private final int mSequence;
63614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov
63714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            public MyLayoutResultCallback(ILayoutResultCallback callback,
63814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    int sequence) {
63914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                mCallback = callback;
64014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                mSequence = sequence;
64114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            }
64214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov
64314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            @Override
64414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
645269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                if (info == null) {
646269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                    throw new NullPointerException("document info cannot be null");
647269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                }
64814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                final ILayoutResultCallback callback;
64914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                synchronized (mLock) {
65014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    callback = mCallback;
65114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    clearLocked();
65214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                }
65314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                if (callback != null) {
65414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    try {
65514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                        callback.onLayoutFinished(info, changed, mSequence);
65614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    } catch (RemoteException re) {
65714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                        Log.e(LOG_TAG, "Error calling onLayoutFinished", re);
65814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    }
65914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                }
66014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            }
66114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov
66214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            @Override
66314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            public void onLayoutFailed(CharSequence error) {
66414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                final ILayoutResultCallback callback;
66514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                synchronized (mLock) {
66614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    callback = mCallback;
66714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    clearLocked();
66814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                }
66914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                if (callback != null) {
67014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    try {
67114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                        callback.onLayoutFailed(error, mSequence);
67214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    } catch (RemoteException re) {
67314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                        Log.e(LOG_TAG, "Error calling onLayoutFailed", re);
67414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    }
67514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                }
67614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            }
67714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov
67814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            @Override
67914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            public void onLayoutCancelled() {
68014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                synchronized (mLock) {
68114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    clearLocked();
68214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                }
68314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            }
68414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov
68514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            private void clearLocked() {
68614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                mLayoutOrWriteCancellation = null;
68714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                mCallback = null;
688db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                doPendingWorkLocked();
68914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            }
69014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov        }
69114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov
69214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov        private final class MyWriteResultCallback extends WriteResultCallback {
693d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov            private ParcelFileDescriptor mFd;
69414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            private int mSequence;
69514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            private IWriteResultCallback mCallback;
69614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov
69714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            public MyWriteResultCallback(IWriteResultCallback callback,
698d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov                    ParcelFileDescriptor fd, int sequence) {
69914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                mFd = fd;
70014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                mSequence = sequence;
70114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                mCallback = callback;
70214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            }
70314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov
70414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            @Override
70514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            public void onWriteFinished(PageRange[] pages) {
70614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                final IWriteResultCallback callback;
70714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                synchronized (mLock) {
70814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    callback = mCallback;
70914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    clearLocked();
71014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                }
71114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                if (pages == null) {
71214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    throw new IllegalArgumentException("pages cannot be null");
71314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                }
71414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                if (pages.length == 0) {
71514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    throw new IllegalArgumentException("pages cannot be empty");
71614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                }
71714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                if (callback != null) {
71814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    try {
71914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                        callback.onWriteFinished(pages, mSequence);
72014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    } catch (RemoteException re) {
72114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                        Log.e(LOG_TAG, "Error calling onWriteFinished", re);
72214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    }
72314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                }
72414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            }
72514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov
72614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            @Override
72714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            public void onWriteFailed(CharSequence error) {
72814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                final IWriteResultCallback callback;
72914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                synchronized (mLock) {
73014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    callback = mCallback;
73114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    clearLocked();
73214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                }
73314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                if (callback != null) {
73414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    try {
73514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                        callback.onWriteFailed(error, mSequence);
73614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    } catch (RemoteException re) {
73714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                        Log.e(LOG_TAG, "Error calling onWriteFailed", re);
73814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    }
73914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                }
74014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            }
74114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov
74214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            @Override
74314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            public void onWriteCancelled() {
74414db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                synchronized (mLock) {
74514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                    clearLocked();
74614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                }
74714db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            }
74814db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov
74914db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            private void clearLocked() {
75014db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                mLayoutOrWriteCancellation = null;
75114db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                IoUtils.closeQuietly(mFd);
75214db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                mCallback = null;
75314db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov                mFd = null;
754db63677c7c02cad7c25627533e5add5ed46870f8Svetoslav Ganov                doPendingWorkLocked();
75514db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov            }
75614db9654f6c31e94fe9272776f1f1b8602a17fdcSvetoslav Ganov        }
7574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
758704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov
759704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov    private static final class PrintJobStateChangeListenerWrapper extends
760704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            IPrintJobStateChangeListener.Stub {
761704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        private final WeakReference<PrintJobStateChangeListener> mWeakListener;
762a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        private final WeakReference<Handler> mWeakHandler;
763704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov
764a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        public PrintJobStateChangeListenerWrapper(PrintJobStateChangeListener listener,
765a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                Handler handler) {
766704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            mWeakListener = new WeakReference<PrintJobStateChangeListener>(listener);
767a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            mWeakHandler = new WeakReference<Handler>(handler);
768704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        }
769704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov
770704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        @Override
771704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        public void onPrintJobStateChanged(PrintJobId printJobId) {
772a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            Handler handler = mWeakHandler.get();
773704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            PrintJobStateChangeListener listener = mWeakListener.get();
774a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            if (handler != null && listener != null) {
775a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                SomeArgs args = SomeArgs.obtain();
776d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov                args.arg1 = this;
777a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                args.arg2 = printJobId;
778a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                handler.obtainMessage(MSG_NOTIFY_PRINT_JOB_STATE_CHANGED,
779a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                        args).sendToTarget();
780704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            }
781704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        }
782a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov
783d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov        public void destroy() {
784d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov            mWeakListener.clear();
785d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov        }
786d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov
787d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov        public PrintJobStateChangeListener getListener() {
788d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov            return mWeakListener.get();
789d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov        }
790d91cb3ea61ea5096637c5d2b5e3e6147d0d2cce3Svetoslav Ganov    }
7914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov}
792