1a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav/*
2a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * Copyright (C) 2014 The Android Open Source Project
3a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav *
4a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * Licensed under the Apache License, Version 2.0 (the "License");
5a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * you may not use this file except in compliance with the License.
6a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * You may obtain a copy of the License at
7a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav *
8a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav *      http://www.apache.org/licenses/LICENSE-2.0
9a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav *
10a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * Unless required by applicable law or agreed to in writing, software
11a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * distributed under the License is distributed on an "AS IS" BASIS,
12a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * See the License for the specific language governing permissions and
14a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * limitations under the License.
15a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav */
16a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
17a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavpackage com.android.printspooler.model;
18a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
19a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.content.ContentResolver;
20a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.content.Context;
21a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.net.Uri;
22a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.os.AsyncTask;
23a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.os.Bundle;
24a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.os.Handler;
25a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.os.IBinder.DeathRecipient;
26a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.os.ICancellationSignal;
27a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.os.Looper;
28a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.os.Message;
29a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.os.ParcelFileDescriptor;
30a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.os.RemoteException;
31a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.print.ILayoutResultCallback;
32a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.print.IPrintDocumentAdapter;
33a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.print.IPrintDocumentAdapterObserver;
34a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.print.IWriteResultCallback;
35a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.print.PageRange;
36a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.print.PrintAttributes;
37a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.print.PrintDocumentAdapter;
38a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.print.PrintDocumentInfo;
39a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.util.Log;
40a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
41a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport com.android.printspooler.R;
42a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport com.android.printspooler.util.PageRangeUtils;
43a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
44a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport libcore.io.IoUtils;
45a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
46a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport java.io.File;
47a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport java.io.FileInputStream;
48a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport java.io.FileOutputStream;
49a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport java.io.IOException;
50a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport java.io.InputStream;
51a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport java.io.OutputStream;
52a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport java.lang.ref.WeakReference;
53a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport java.util.Arrays;
54a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
55a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavpublic final class RemotePrintDocument {
56a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final String LOG_TAG = "RemotePrintDocument";
57a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
586f249835a4ff9e7e7e3ca0190b7ecf72e689656dSvetoslav    private static final boolean DEBUG = false;
59a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
60a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final int STATE_INITIAL = 0;
61a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final int STATE_STARTED = 1;
62a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final int STATE_UPDATING = 2;
63a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final int STATE_UPDATED = 3;
64a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final int STATE_FAILED = 4;
65a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final int STATE_FINISHED = 5;
66a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final int STATE_CANCELING = 6;
67a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final int STATE_CANCELED = 7;
68a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final int STATE_DESTROYED = 8;
69a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
70a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private final Context mContext;
71a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
72a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private final RemotePrintDocumentInfo mDocumentInfo;
73a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private final UpdateSpec mUpdateSpec = new UpdateSpec();
74a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
75a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private final Looper mLooper;
76a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private final IPrintDocumentAdapter mPrintDocumentAdapter;
77e17123dd6d3666c88b47172b8efc995523b47346Svetoslav    private final RemoteAdapterDeathObserver mAdapterDeathObserver;
78a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
79a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private final UpdateResultCallbacks mUpdateCallbacks;
80a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
81a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private final CommandDoneCallback mCommandResultCallback =
82a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            new CommandDoneCallback() {
83a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        @Override
84a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void onDone() {
85a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (mCurrentCommand.isCompleted()) {
86a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (mCurrentCommand instanceof LayoutCommand) {
87a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    // If there is a next command after a layout is done, then another
88a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    // update was issued and the next command is another layout, so we
89a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    // do nothing. However, if there is no next command we may need to
90a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    // ask for some pages given we do not already have them or we do
91a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    // but the content has changed.
92a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    if (mNextCommand == null) {
93525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                        if (mUpdateSpec.pages != null && (mDocumentInfo.changed
94525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                                || (mDocumentInfo.info.getPageCount()
95525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                                        != PrintDocumentInfo.PAGE_COUNT_UNKNOWN
96525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                                && !PageRangeUtils.contains(mDocumentInfo.writtenPages,
97525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                                        mUpdateSpec.pages, mDocumentInfo.info.getPageCount())))) {
98a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            mNextCommand = new WriteCommand(mContext, mLooper,
99a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                                    mPrintDocumentAdapter, mDocumentInfo,
100a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                                    mDocumentInfo.info.getPageCount(), mUpdateSpec.pages,
101525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                                    mDocumentInfo.fileProvider, mCommandResultCallback);
102a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        } else {
103525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                            if (mUpdateSpec.pages != null) {
104525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                                // If we have the requested pages, update which ones to be printed.
105525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                                mDocumentInfo.printedPages = PageRangeUtils.computePrintedPages(
106525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                                        mUpdateSpec.pages, mDocumentInfo.writtenPages,
107525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                                        mDocumentInfo.info.getPageCount());
108525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                            }
109a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            // Notify we are done.
11005ff998fd86eff15e91694bc205ea0af0de83284Svet Ganov                            mState = STATE_UPDATED;
111a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            notifyUpdateCompleted();
112a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        }
113a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    }
114a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                } else {
115a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    // We always notify after a write.
11605ff998fd86eff15e91694bc205ea0af0de83284Svet Ganov                    mState = STATE_UPDATED;
117a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    notifyUpdateCompleted();
118a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
119a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                runPendingCommand();
120a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            } else if (mCurrentCommand.isFailed()) {
121a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mState = STATE_FAILED;
122a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                CharSequence error = mCurrentCommand.getError();
123a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mCurrentCommand = null;
124a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mNextCommand = null;
125a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mUpdateSpec.reset();
126a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                notifyUpdateFailed(error);
127a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            } else if (mCurrentCommand.isCanceled()) {
128a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (mState == STATE_CANCELING) {
129a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    mState = STATE_CANCELED;
130a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    notifyUpdateCanceled();
131a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
132a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                runPendingCommand();
133a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
134a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
135a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    };
136a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
137a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private final DeathRecipient mDeathRecipient = new DeathRecipient() {
138a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        @Override
139a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void binderDied() {
1404237c92d850b7fb0fa0be15df94e4d1689e353fcSvet Ganov            onPrintingAppDied();
141a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
142a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    };
143a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
144a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private int mState = STATE_INITIAL;
145a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
146a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private AsyncCommand mCurrentCommand;
147a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private AsyncCommand mNextCommand;
148a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
149e17123dd6d3666c88b47172b8efc995523b47346Svetoslav    public interface RemoteAdapterDeathObserver {
150e17123dd6d3666c88b47172b8efc995523b47346Svetoslav        public void onDied();
151a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
152a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
153a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public interface UpdateResultCallbacks {
154a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void onUpdateCompleted(RemotePrintDocumentInfo document);
155a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void onUpdateCanceled();
156a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void onUpdateFailed(CharSequence error);
157a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
158a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
159a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public RemotePrintDocument(Context context, IPrintDocumentAdapter adapter,
160e17123dd6d3666c88b47172b8efc995523b47346Svetoslav            MutexFileProvider fileProvider, RemoteAdapterDeathObserver deathObserver,
161525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            UpdateResultCallbacks callbacks) {
162a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mPrintDocumentAdapter = adapter;
163a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mLooper = context.getMainLooper();
164a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mContext = context;
165e17123dd6d3666c88b47172b8efc995523b47346Svetoslav        mAdapterDeathObserver = deathObserver;
166a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mDocumentInfo = new RemotePrintDocumentInfo();
167525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        mDocumentInfo.fileProvider = fileProvider;
168a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mUpdateCallbacks = callbacks;
169a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        connectToRemoteDocument();
170a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
171a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
172a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public void start() {
173a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (DEBUG) {
174a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.i(LOG_TAG, "[CALLED] start()");
175a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
176a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (mState != STATE_INITIAL) {
177a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            throw new IllegalStateException("Cannot start in state:" + stateToString(mState));
178a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
179a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        try {
180a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mPrintDocumentAdapter.start();
181a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_STARTED;
182a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        } catch (RemoteException re) {
183a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.e(LOG_TAG, "Error calling start()", re);
184a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_FAILED;
185a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
186a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
187a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
188a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public boolean update(PrintAttributes attributes, PageRange[] pages, boolean preview) {
189a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        boolean willUpdate;
190a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
191a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (DEBUG) {
192a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.i(LOG_TAG, "[CALLED] update()");
193a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
194a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
195a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (hasUpdateError()) {
196a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            throw new IllegalStateException("Cannot update without a clearing the failure");
197a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
198a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
199a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (mState == STATE_INITIAL || mState == STATE_FINISHED || mState == STATE_DESTROYED) {
200a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            throw new IllegalStateException("Cannot update in state:" + stateToString(mState));
201a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
202a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
203a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        // We schedule a layout if the constraints changed.
204a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (!mUpdateSpec.hasSameConstraints(attributes, preview)) {
205a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            willUpdate = true;
206a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
207a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // If there is a current command that is running we ask for a
208a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // cancellation and start over.
209a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (mCurrentCommand != null && (mCurrentCommand.isRunning()
210a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    || mCurrentCommand.isPending())) {
211a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mCurrentCommand.cancel();
212a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
213a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
214a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Schedule a layout command.
215a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            PrintAttributes oldAttributes = mDocumentInfo.attributes != null
216a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    ? mDocumentInfo.attributes : new PrintAttributes.Builder().build();
217a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            AsyncCommand command = new LayoutCommand(mLooper, mPrintDocumentAdapter,
218a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                  mDocumentInfo, oldAttributes, attributes, preview, mCommandResultCallback);
219a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            scheduleCommand(command);
220a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
221a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_UPDATING;
222a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        // If no layout in progress and we don't have all pages - schedule a write.
223a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        } else if ((!(mCurrentCommand instanceof LayoutCommand)
224a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                || (!mCurrentCommand.isPending() && !mCurrentCommand.isRunning()))
225525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                && pages != null && !PageRangeUtils.contains(mUpdateSpec.pages, pages,
226525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                mDocumentInfo.info.getPageCount())) {
227a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            willUpdate = true;
228a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
229a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Cancel the current write as a new one is to be scheduled.
230a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (mCurrentCommand instanceof WriteCommand
231a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    && (mCurrentCommand.isPending() || mCurrentCommand.isRunning())) {
232a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mCurrentCommand.cancel();
233a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
234a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
235a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Schedule a write command.
236a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            AsyncCommand command = new WriteCommand(mContext, mLooper, mPrintDocumentAdapter,
237a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    mDocumentInfo, mDocumentInfo.info.getPageCount(), pages,
238525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                    mDocumentInfo.fileProvider, mCommandResultCallback);
239a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            scheduleCommand(command);
240a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
241a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_UPDATING;
242a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        } else {
243a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            willUpdate = false;
244a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (DEBUG) {
245a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Log.i(LOG_TAG, "[SKIPPING] No update needed");
246a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
247a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
248a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
249a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        // Keep track of what is requested.
250a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mUpdateSpec.update(attributes, preview, pages);
251a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
252a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        runPendingCommand();
253a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
254a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        return willUpdate;
255a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
256a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
257a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public void finish() {
258a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (DEBUG) {
259a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.i(LOG_TAG, "[CALLED] finish()");
260a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
261a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (mState != STATE_STARTED && mState != STATE_UPDATED
2629c9888b8c59e35717ecfc32e9b96fb8702ceb480Svetoslav                && mState != STATE_FAILED && mState != STATE_CANCELING
2639c9888b8c59e35717ecfc32e9b96fb8702ceb480Svetoslav                && mState != STATE_CANCELED) {
264a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            throw new IllegalStateException("Cannot finish in state:"
265a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    + stateToString(mState));
266a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
267a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        try {
268a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mPrintDocumentAdapter.finish();
269a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_FINISHED;
270a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        } catch (RemoteException re) {
2714237c92d850b7fb0fa0be15df94e4d1689e353fcSvet Ganov            Log.e(LOG_TAG, "Error calling finish()");
272a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_FAILED;
273a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
274a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
275a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
276a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public void cancel() {
277a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (DEBUG) {
278a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.i(LOG_TAG, "[CALLED] cancel()");
279a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
280a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
281a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (mState == STATE_CANCELING) {
282a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return;
283a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
284a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
285a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (mState != STATE_UPDATING) {
286a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            throw new IllegalStateException("Cannot cancel in state:" + stateToString(mState));
287a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
288a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
289a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mState = STATE_CANCELING;
290a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
291a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mCurrentCommand.cancel();
292a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
293a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
294a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public void destroy() {
295a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (DEBUG) {
296a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.i(LOG_TAG, "[CALLED] destroy()");
297a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
298a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (mState == STATE_DESTROYED) {
299a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            throw new IllegalStateException("Cannot destroy in state:" + stateToString(mState));
300a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
301a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
302a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mState = STATE_DESTROYED;
303a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
304a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        disconnectFromRemoteDocument();
305a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
306a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
307fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov    public void kill(String reason) {
308fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov        if (DEBUG) {
309fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov            Log.i(LOG_TAG, "[CALLED] kill()");
310fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov        }
311fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov
312fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov        try {
313fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov            mPrintDocumentAdapter.kill(reason);
314fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov        } catch (RemoteException re) {
315fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov            Log.e(LOG_TAG, "Error calling kill()", re);
316fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov        }
317fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov    }
318fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov
319a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public boolean isUpdating() {
320a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        return mState == STATE_UPDATING || mState == STATE_CANCELING;
321a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
322a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
323a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public boolean isDestroyed() {
324a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        return mState == STATE_DESTROYED;
325a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
326a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
327a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public boolean hasUpdateError() {
328a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        return mState == STATE_FAILED;
329a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
330a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
3316552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav    public boolean hasLaidOutPages() {
3326552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav        return mDocumentInfo.info != null
3336552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav                && mDocumentInfo.info.getPageCount() > 0;
3346552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav    }
3356552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav
336a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public void clearUpdateError() {
337a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (!hasUpdateError()) {
338a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            throw new IllegalStateException("No update error to clear");
339a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
340a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mState = STATE_STARTED;
341a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
342a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
343a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public RemotePrintDocumentInfo getDocumentInfo() {
344a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        return mDocumentInfo;
345a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
346a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
347a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public void writeContent(ContentResolver contentResolver, Uri uri) {
348525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        File file = null;
349a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        InputStream in = null;
350a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        OutputStream out = null;
351a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        try {
352525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            file = mDocumentInfo.fileProvider.acquireFile(null);
353525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            in = new FileInputStream(file);
354a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            out = contentResolver.openOutputStream(uri);
355a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            final byte[] buffer = new byte[8192];
356a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            while (true) {
357a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                final int readByteCount = in.read(buffer);
358a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (readByteCount < 0) {
359a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    break;
360a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
361a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                out.write(buffer, 0, readByteCount);
362a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
363a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        } catch (IOException e) {
364a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.e(LOG_TAG, "Error writing document content.", e);
365a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        } finally {
366a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            IoUtils.closeQuietly(in);
367a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            IoUtils.closeQuietly(out);
368525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            if (file != null) {
369525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                mDocumentInfo.fileProvider.releaseFile();
370525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            }
371a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
372a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
373a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
374a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private void notifyUpdateCanceled() {
375a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (DEBUG) {
376a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.i(LOG_TAG, "[CALLING] onUpdateCanceled()");
377a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
378a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mUpdateCallbacks.onUpdateCanceled();
379a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
380a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
381a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private void notifyUpdateCompleted() {
382a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (DEBUG) {
383a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.i(LOG_TAG, "[CALLING] onUpdateCompleted()");
384a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
385a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mUpdateCallbacks.onUpdateCompleted(mDocumentInfo);
386a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
387a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
388a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private void notifyUpdateFailed(CharSequence error) {
389a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (DEBUG) {
390a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.i(LOG_TAG, "[CALLING] onUpdateCompleted()");
391a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
392a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mUpdateCallbacks.onUpdateFailed(error);
393a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
394a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
395a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private void connectToRemoteDocument() {
396a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        try {
397a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mPrintDocumentAdapter.asBinder().linkToDeath(mDeathRecipient, 0);
398a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        } catch (RemoteException re) {
399a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.w(LOG_TAG, "The printing process is dead.");
400a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            destroy();
401a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return;
402a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
403a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
404a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        try {
405a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mPrintDocumentAdapter.setObserver(new PrintDocumentAdapterObserver(this));
406a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        } catch (RemoteException re) {
407a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.w(LOG_TAG, "Error setting observer to the print adapter.");
408a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            destroy();
409a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
410a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
411a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
412a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private void disconnectFromRemoteDocument() {
413a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        try {
414a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mPrintDocumentAdapter.setObserver(null);
415a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        } catch (RemoteException re) {
416a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.w(LOG_TAG, "Error setting observer to the print adapter.");
417a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Keep going - best effort...
418a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
419a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
420a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mPrintDocumentAdapter.asBinder().unlinkToDeath(mDeathRecipient, 0);
421a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
422a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
423a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private void scheduleCommand(AsyncCommand command) {
424a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (mCurrentCommand == null) {
425a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mCurrentCommand = command;
426a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        } else {
427a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mNextCommand = command;
428a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
429a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
430a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
431a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private void runPendingCommand() {
432a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (mCurrentCommand != null
433a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                && (mCurrentCommand.isCompleted()
434a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        || mCurrentCommand.isCanceled())) {
435a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mCurrentCommand = mNextCommand;
436a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mNextCommand = null;
437a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
438a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
439a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (mCurrentCommand != null) {
440a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (mCurrentCommand.isPending()) {
441a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mCurrentCommand.run();
442a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
443a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_UPDATING;
444a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        } else {
445a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_UPDATED;
446a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
447a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
448a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
449a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static String stateToString(int state) {
450a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        switch (state) {
451a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            case STATE_FINISHED: {
452a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return "STATE_FINISHED";
453a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
454a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            case STATE_FAILED: {
455a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return "STATE_FAILED";
456a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
457a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            case STATE_STARTED: {
458a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return "STATE_STARTED";
459a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
460a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            case STATE_UPDATING: {
461a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return "STATE_UPDATING";
462a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
463a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            case STATE_UPDATED: {
464a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return "STATE_UPDATED";
465a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
466a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            case STATE_CANCELING: {
467a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return "STATE_CANCELING";
468a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
469a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            case STATE_CANCELED: {
470a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return "STATE_CANCELED";
471a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
472a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            case STATE_DESTROYED: {
473a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return "STATE_DESTROYED";
474a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
475a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            default: {
476a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return "STATE_UNKNOWN";
477a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
478a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
479a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
480a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
481a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    static final class UpdateSpec {
482a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        final PrintAttributes attributes = new PrintAttributes.Builder().build();
483a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        boolean preview;
484a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        PageRange[] pages;
485a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
486a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void update(PrintAttributes attributes, boolean preview,
487a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                PageRange[] pages) {
488a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            this.attributes.copyFrom(attributes);
489a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            this.preview = preview;
490525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            this.pages = (pages != null) ? Arrays.copyOf(pages, pages.length) : null;
491a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
492a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
493a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void reset() {
494a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            attributes.clear();
495a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            preview = false;
496a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            pages = null;
497a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
498a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
499a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public boolean hasSameConstraints(PrintAttributes attributes, boolean preview) {
500a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return this.attributes.equals(attributes) && this.preview == preview;
501a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
502a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
503a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
504a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public static final class RemotePrintDocumentInfo {
505a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public PrintAttributes attributes;
506a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public Bundle metadata;
507a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public PrintDocumentInfo info;
508a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public PageRange[] printedPages;
509a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public PageRange[] writtenPages;
510525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        public MutexFileProvider fileProvider;
511525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        public boolean changed;
512525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        public boolean updated;
513525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        public boolean laidout;
514a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
515a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
516a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private interface CommandDoneCallback {
517a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void onDone();
518a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
519a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
520a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static abstract class AsyncCommand implements Runnable {
521a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private static final int STATE_PENDING = 0;
522a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private static final int STATE_RUNNING = 1;
523a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private static final int STATE_COMPLETED = 2;
524a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private static final int STATE_CANCELED = 3;
525a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private static final int STATE_CANCELING = 4;
526a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private static final int STATE_FAILED = 5;
527a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
528a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private static int sSequenceCounter;
529a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
530a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected final int mSequence = sSequenceCounter++;
531a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected final IPrintDocumentAdapter mAdapter;
532a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected final RemotePrintDocumentInfo mDocument;
533a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
534a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected final CommandDoneCallback mDoneCallback;
535a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
536a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected ICancellationSignal mCancellation;
537a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
538a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private CharSequence mError;
539a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
540a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private int mState = STATE_PENDING;
541a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
542a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public AsyncCommand(IPrintDocumentAdapter adapter, RemotePrintDocumentInfo document,
543a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                CommandDoneCallback doneCallback) {
544a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mAdapter = adapter;
545a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mDocument = document;
546a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mDoneCallback = doneCallback;
547a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
548a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
549a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected final boolean isCanceling() {
550a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return mState == STATE_CANCELING;
551a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
552a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
553a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public final boolean isCanceled() {
554a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return mState == STATE_CANCELED;
555a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
556a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
557a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public final void cancel() {
558a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (isRunning()) {
559a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                canceling();
560a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (mCancellation != null) {
561a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    try {
562a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        mCancellation.cancel();
563a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } catch (RemoteException re) {
564a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        Log.w(LOG_TAG, "Error while canceling", re);
565a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    }
566a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
567a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            } else {
568a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                canceled();
569a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
570a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                // Done.
571a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mDoneCallback.onDone();
572a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
573a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
574a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
575a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected final void canceling() {
576a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (mState != STATE_PENDING && mState != STATE_RUNNING) {
577a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                throw new IllegalStateException("Command not pending or running.");
578a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
579a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_CANCELING;
580a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
581a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
582a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected final void canceled() {
583a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (mState != STATE_CANCELING) {
584a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                throw new IllegalStateException("Not canceling.");
585a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
586a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_CANCELED;
587a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
588a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
589a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public final boolean isPending() {
590a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return mState == STATE_PENDING;
591a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
592a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
593a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected final void running() {
594a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (mState != STATE_PENDING) {
595a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                throw new IllegalStateException("Not pending.");
596a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
597a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_RUNNING;
598a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
599a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
600a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public final boolean isRunning() {
601a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return mState == STATE_RUNNING;
602a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
603a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
604a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected final void completed() {
605a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (mState != STATE_RUNNING && mState != STATE_CANCELING) {
606a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                throw new IllegalStateException("Not running.");
607a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
608a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_COMPLETED;
609a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
610a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
611a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public final boolean isCompleted() {
612a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return mState == STATE_COMPLETED;
613a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
614a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
615a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected final void failed(CharSequence error) {
616a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (mState != STATE_RUNNING) {
617a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                throw new IllegalStateException("Not running.");
618a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
619a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_FAILED;
620a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
621a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mError = error;
622a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
623a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
624a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public final boolean isFailed() {
625a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return mState == STATE_FAILED;
626a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
627a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
628a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public CharSequence getError() {
629a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return mError;
630a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
631a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
632a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
633a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final class LayoutCommand extends AsyncCommand {
634a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final PrintAttributes mOldAttributes = new PrintAttributes.Builder().build();
635a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final PrintAttributes mNewAttributes = new PrintAttributes.Builder().build();
636a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final Bundle mMetadata = new Bundle();
637a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
638a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final ILayoutResultCallback mRemoteResultCallback;
639a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
640a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final Handler mHandler;
641a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
642a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public LayoutCommand(Looper looper, IPrintDocumentAdapter adapter,
643a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                RemotePrintDocumentInfo document, PrintAttributes oldAttributes,
644a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                PrintAttributes newAttributes, boolean preview, CommandDoneCallback callback) {
645a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            super(adapter, document, callback);
646a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mHandler = new LayoutHandler(looper);
647a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mRemoteResultCallback = new LayoutResultCallback(mHandler);
648a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mOldAttributes.copyFrom(oldAttributes);
649a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mNewAttributes.copyFrom(newAttributes);
650a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mMetadata.putBoolean(PrintDocumentAdapter.EXTRA_PRINT_PREVIEW, preview);
651a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
652a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
653a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        @Override
654a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void run() {
655a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            running();
656a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
657a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            try {
658a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (DEBUG) {
659a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    Log.i(LOG_TAG, "[PERFORMING] layout");
660a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
661525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                mDocument.changed = false;
662a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mAdapter.layout(mOldAttributes, mNewAttributes, mRemoteResultCallback,
663a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        mMetadata, mSequence);
664a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            } catch (RemoteException re) {
665a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Log.e(LOG_TAG, "Error calling layout", re);
666a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                handleOnLayoutFailed(null, mSequence);
667a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
668a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
669a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
670a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private void handleOnLayoutStarted(ICancellationSignal cancellation, int sequence) {
671a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (sequence != mSequence) {
672a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return;
673a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
674a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
675a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (DEBUG) {
676a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Log.i(LOG_TAG, "[CALLBACK] onLayoutStarted");
677a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
678a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
679a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (isCanceling()) {
680a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                try {
681a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    cancellation.cancel();
682a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                } catch (RemoteException re) {
683a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    Log.e(LOG_TAG, "Error cancelling", re);
684a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    handleOnLayoutFailed(null, mSequence);
685a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
686a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            } else {
687a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mCancellation = cancellation;
688a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
689a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
690a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
691a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private void handleOnLayoutFinished(PrintDocumentInfo info,
692a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                boolean changed, int sequence) {
693a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (sequence != mSequence) {
694a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return;
695a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
696a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
697a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (DEBUG) {
698a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Log.i(LOG_TAG, "[CALLBACK] onLayoutFinished");
699a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
700a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
701a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            completed();
702a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
703a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // If the document description changed or the content in the
704a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // document changed, the we need to invalidate the pages.
705a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (changed || !equalsIgnoreSize(mDocument.info, info)) {
706a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                // If the content changed we throw away all pages as
707a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                // we will request them again with the new content.
708a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mDocument.writtenPages = null;
709a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mDocument.printedPages = null;
710525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                mDocument.changed = true;
711a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
712a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
713a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Update the document with data from the layout pass.
714a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mDocument.attributes = mNewAttributes;
715a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mDocument.metadata = mMetadata;
716525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            mDocument.laidout = true;
717a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mDocument.info = info;
718a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
719a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Release the remote cancellation interface.
720a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mCancellation = null;
721a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
722a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Done.
723a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mDoneCallback.onDone();
724a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
725a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
726a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private void handleOnLayoutFailed(CharSequence error, int sequence) {
727a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (sequence != mSequence) {
728a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return;
729a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
730a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
731a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (DEBUG) {
732a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Log.i(LOG_TAG, "[CALLBACK] onLayoutFailed");
733a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
734a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
735525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            mDocument.laidout = false;
736525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov
737a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            failed(error);
738a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
739a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Release the remote cancellation interface.
740a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mCancellation = null;
741a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
742a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Failed.
743a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mDoneCallback.onDone();
744a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
745a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
746a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private void handleOnLayoutCanceled(int sequence) {
747a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (sequence != mSequence) {
748a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return;
749a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
750a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
751a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (DEBUG) {
752a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Log.i(LOG_TAG, "[CALLBACK] onLayoutCanceled");
753a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
754a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
755a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            canceled();
756a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
757a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Release the remote cancellation interface.
758a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mCancellation = null;
759a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
760a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Done.
761a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mDoneCallback.onDone();
762a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
763a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
764a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private boolean equalsIgnoreSize(PrintDocumentInfo lhs, PrintDocumentInfo rhs) {
765a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (lhs == rhs) {
766a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return true;
767a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
768a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (lhs == null) {
769a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return false;
770a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            } else {
771a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (rhs == null) {
772a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    return false;
773a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
774a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (lhs.getContentType() != rhs.getContentType()
775a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        || lhs.getPageCount() != rhs.getPageCount()) {
776a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    return false;
777a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
778a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
779a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return true;
780a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
781a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
782a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final class LayoutHandler extends Handler {
783a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public static final int MSG_ON_LAYOUT_STARTED = 1;
784a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public static final int MSG_ON_LAYOUT_FINISHED = 2;
785a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public static final int MSG_ON_LAYOUT_FAILED = 3;
786a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public static final int MSG_ON_LAYOUT_CANCELED = 4;
787a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
788a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public LayoutHandler(Looper looper) {
789a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                super(looper, null, false);
790a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
791a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
792a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            @Override
793a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public void handleMessage(Message message) {
794a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                switch (message.what) {
795a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    case MSG_ON_LAYOUT_STARTED: {
796a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        ICancellationSignal cancellation = (ICancellationSignal) message.obj;
797a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        final int sequence = message.arg1;
798a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        handleOnLayoutStarted(cancellation, sequence);
799a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } break;
800a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
801a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    case MSG_ON_LAYOUT_FINISHED: {
802a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        PrintDocumentInfo info = (PrintDocumentInfo) message.obj;
803a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        final boolean changed = (message.arg1 == 1);
804a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        final int sequence = message.arg2;
805a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        handleOnLayoutFinished(info, changed, sequence);
806a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } break;
807a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
808a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    case MSG_ON_LAYOUT_FAILED: {
809a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        CharSequence error = (CharSequence) message.obj;
810a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        final int sequence = message.arg1;
811a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        handleOnLayoutFailed(error, sequence);
812a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } break;
813a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
814a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    case MSG_ON_LAYOUT_CANCELED: {
815a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        final int sequence = message.arg1;
816a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        handleOnLayoutCanceled(sequence);
817a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } break;
818a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
819a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
820a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
821a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
822a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private static final class LayoutResultCallback extends ILayoutResultCallback.Stub {
823a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            private final WeakReference<Handler> mWeakHandler;
824a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
825a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public LayoutResultCallback(Handler handler) {
826a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mWeakHandler = new WeakReference<>(handler);
827a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
828a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
829a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            @Override
830a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public void onLayoutStarted(ICancellationSignal cancellation, int sequence) {
831a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Handler handler = mWeakHandler.get();
832a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (handler != null) {
833a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    handler.obtainMessage(LayoutHandler.MSG_ON_LAYOUT_STARTED,
834a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            sequence, 0, cancellation).sendToTarget();
835a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
836a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
837a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
838a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            @Override
839a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public void onLayoutFinished(PrintDocumentInfo info, boolean changed, int sequence) {
840a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Handler handler = mWeakHandler.get();
841a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (handler != null) {
842a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    handler.obtainMessage(LayoutHandler.MSG_ON_LAYOUT_FINISHED,
843a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            changed ? 1 : 0, sequence, info).sendToTarget();
844a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
845a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
846a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
847a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            @Override
848a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public void onLayoutFailed(CharSequence error, int sequence) {
849a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Handler handler = mWeakHandler.get();
850a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (handler != null) {
851a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    handler.obtainMessage(LayoutHandler.MSG_ON_LAYOUT_FAILED,
852a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            sequence, 0, error).sendToTarget();
853a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
854a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
855a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
856a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            @Override
857a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public void onLayoutCanceled(int sequence) {
858a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Handler handler = mWeakHandler.get();
859a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (handler != null) {
860a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    handler.obtainMessage(LayoutHandler.MSG_ON_LAYOUT_CANCELED,
861a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            sequence, 0).sendToTarget();
862a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
863a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
864a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
865a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
866a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
867a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final class WriteCommand extends AsyncCommand {
868a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final int mPageCount;
869a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final PageRange[] mPages;
870525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        private final MutexFileProvider mFileProvider;
871a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
872a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final IWriteResultCallback mRemoteResultCallback;
873a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final CommandDoneCallback mDoneCallback;
874a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
875a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final Context mContext;
876a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final Handler mHandler;
877a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
878a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public WriteCommand(Context context, Looper looper, IPrintDocumentAdapter adapter,
879a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                RemotePrintDocumentInfo document, int pageCount, PageRange[] pages,
880525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                MutexFileProvider fileProvider, CommandDoneCallback callback) {
881a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            super(adapter, document, callback);
882a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mContext = context;
883a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mHandler = new WriteHandler(looper);
884a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mRemoteResultCallback = new WriteResultCallback(mHandler);
885a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mPageCount = pageCount;
886a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mPages = Arrays.copyOf(pages, pages.length);
887525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            mFileProvider = fileProvider;
888a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mDoneCallback = callback;
889a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
890a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
891a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        @Override
892a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void run() {
893a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            running();
894a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
895a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // This is a long running operation as we will be reading fully
896a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // the written data. In case of a cancellation, we ask the client
897a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // to stop writing data and close the file descriptor after
898a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // which we will reach the end of the stream, thus stop reading.
899a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            new AsyncTask<Void, Void, Void>() {
900a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                @Override
901a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                protected Void doInBackground(Void... params) {
902525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                    File file = null;
903a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    InputStream in = null;
904a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    OutputStream out = null;
905a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    ParcelFileDescriptor source = null;
906a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    ParcelFileDescriptor sink = null;
907a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    try {
908525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                        file = mFileProvider.acquireFile(null);
909a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
910a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        source = pipe[0];
911a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        sink = pipe[1];
912a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
913a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        in = new FileInputStream(source.getFileDescriptor());
914525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                        out = new FileOutputStream(file);
915a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
916a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        // Async call to initiate the other process writing the data.
917a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        if (DEBUG) {
918a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            Log.i(LOG_TAG, "[PERFORMING] write");
919a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        }
920a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        mAdapter.write(mPages, sink, mRemoteResultCallback, mSequence);
921a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
922a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        // Close the source. It is now held by the client.
923a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        sink.close();
924a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        sink = null;
925a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
926a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        // Read the data.
927a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        final byte[] buffer = new byte[8192];
928a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        while (true) {
929a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            final int readByteCount = in.read(buffer);
930a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            if (readByteCount < 0) {
931a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                                break;
932a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            }
933a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            out.write(buffer, 0, readByteCount);
934a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        }
935a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } catch (RemoteException | IOException e) {
936a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        Log.e(LOG_TAG, "Error calling write()", e);
937a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } finally {
938a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        IoUtils.closeQuietly(in);
939a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        IoUtils.closeQuietly(out);
940a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        IoUtils.closeQuietly(sink);
941a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        IoUtils.closeQuietly(source);
942525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                        if (file != null) {
943525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                            mFileProvider.releaseFile();
944525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                        }
945a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    }
946a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    return null;
947a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
948a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
949a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
950a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
951a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private void handleOnWriteStarted(ICancellationSignal cancellation, int sequence) {
952a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (sequence != mSequence) {
953a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return;
954a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
955a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
956a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (DEBUG) {
957a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Log.i(LOG_TAG, "[CALLBACK] onWriteStarted");
958a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
959a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
960a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (isCanceling()) {
961a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                try {
962a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    cancellation.cancel();
963a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                } catch (RemoteException re) {
964a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    Log.e(LOG_TAG, "Error cancelling", re);
965a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    handleOnWriteFailed(null, sequence);
966a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
967a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            } else {
968a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mCancellation = cancellation;
969a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
970a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
971a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
972a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private void handleOnWriteFinished(PageRange[] pages, int sequence) {
973a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (sequence != mSequence) {
974a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return;
975a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
976a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
977a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (DEBUG) {
978a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Log.i(LOG_TAG, "[CALLBACK] onWriteFinished");
979a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
980a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
981a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            PageRange[] writtenPages = PageRangeUtils.normalize(pages);
982525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            PageRange[] printedPages = PageRangeUtils.computePrintedPages(
983525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                    mPages, writtenPages, mPageCount);
984a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
985a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Handle if we got invalid pages
986a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (printedPages != null) {
987a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mDocument.writtenPages = writtenPages;
988a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mDocument.printedPages = printedPages;
989a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                completed();
990a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            } else {
991a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mDocument.writtenPages = null;
992a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mDocument.printedPages = null;
993a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                failed(mContext.getString(R.string.print_error_default_message));
994a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
995a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
996a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Release the remote cancellation interface.
997a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mCancellation = null;
998a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
999a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Done.
1000a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mDoneCallback.onDone();
1001a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
1002a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1003a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private void handleOnWriteFailed(CharSequence error, int sequence) {
1004a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (sequence != mSequence) {
1005a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return;
1006a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1007a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1008a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (DEBUG) {
1009a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Log.i(LOG_TAG, "[CALLBACK] onWriteFailed");
1010a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1011a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1012a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            failed(error);
1013a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1014a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Release the remote cancellation interface.
1015a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mCancellation = null;
1016a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1017a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Done.
1018a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mDoneCallback.onDone();
1019a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
1020a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1021a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private void handleOnWriteCanceled(int sequence) {
1022a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (sequence != mSequence) {
1023a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return;
1024a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1025a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1026a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (DEBUG) {
1027a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Log.i(LOG_TAG, "[CALLBACK] onWriteCanceled");
1028a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1029a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1030a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            canceled();
1031a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1032a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Release the remote cancellation interface.
1033a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mCancellation = null;
1034a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1035a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Done.
1036a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mDoneCallback.onDone();
1037a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
1038a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1039a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final class WriteHandler extends Handler {
1040a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public static final int MSG_ON_WRITE_STARTED = 1;
1041a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public static final int MSG_ON_WRITE_FINISHED = 2;
1042a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public static final int MSG_ON_WRITE_FAILED = 3;
1043a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public static final int MSG_ON_WRITE_CANCELED = 4;
1044a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1045a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public WriteHandler(Looper looper) {
1046a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                super(looper, null, false);
1047a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1048a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1049a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            @Override
1050a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public void handleMessage(Message message) {
1051a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                switch (message.what) {
1052a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    case MSG_ON_WRITE_STARTED: {
1053a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        ICancellationSignal cancellation = (ICancellationSignal) message.obj;
1054a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        final int sequence = message.arg1;
1055a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        handleOnWriteStarted(cancellation, sequence);
1056a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } break;
1057a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1058a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    case MSG_ON_WRITE_FINISHED: {
1059a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        PageRange[] pages = (PageRange[]) message.obj;
1060a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        final int sequence = message.arg1;
1061a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        handleOnWriteFinished(pages, sequence);
1062a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } break;
1063a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1064a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    case MSG_ON_WRITE_FAILED: {
1065a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        CharSequence error = (CharSequence) message.obj;
1066a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        final int sequence = message.arg1;
1067a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        handleOnWriteFailed(error, sequence);
1068a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } break;
1069a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1070a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    case MSG_ON_WRITE_CANCELED: {
1071a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        final int sequence = message.arg1;
1072a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        handleOnWriteCanceled(sequence);
1073a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } break;
1074a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
1075a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1076a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
1077a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1078a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private static final class WriteResultCallback extends IWriteResultCallback.Stub {
1079a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            private final WeakReference<Handler> mWeakHandler;
1080a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1081a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public WriteResultCallback(Handler handler) {
1082a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mWeakHandler = new WeakReference<>(handler);
1083a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1084a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1085a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            @Override
1086a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public void onWriteStarted(ICancellationSignal cancellation, int sequence) {
1087a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Handler handler = mWeakHandler.get();
1088a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (handler != null) {
1089a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    handler.obtainMessage(WriteHandler.MSG_ON_WRITE_STARTED,
1090a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            sequence, 0, cancellation).sendToTarget();
1091a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
1092a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1093a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1094a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            @Override
1095a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public void onWriteFinished(PageRange[] pages, int sequence) {
1096a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Handler handler = mWeakHandler.get();
1097a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (handler != null) {
1098a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    handler.obtainMessage(WriteHandler.MSG_ON_WRITE_FINISHED,
1099a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            sequence, 0, pages).sendToTarget();
1100a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
1101a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1102a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1103a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            @Override
1104a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public void onWriteFailed(CharSequence error, int sequence) {
1105a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Handler handler = mWeakHandler.get();
1106a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (handler != null) {
1107a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    handler.obtainMessage(WriteHandler.MSG_ON_WRITE_FAILED,
1108a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        sequence, 0, error).sendToTarget();
1109a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
1110a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1111a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1112a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            @Override
1113a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public void onWriteCanceled(int sequence) {
1114a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Handler handler = mWeakHandler.get();
1115a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (handler != null) {
1116a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    handler.obtainMessage(WriteHandler.MSG_ON_WRITE_CANCELED,
1117a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        sequence, 0).sendToTarget();
1118a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
1119a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1120a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
1121a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
1122a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
11234237c92d850b7fb0fa0be15df94e4d1689e353fcSvet Ganov    private void onPrintingAppDied() {
11244237c92d850b7fb0fa0be15df94e4d1689e353fcSvet Ganov        mState = STATE_FAILED;
11252fb64a5cb160a2615f07ed669aa5738dbb74ad6cSvetoslav        new Handler(mLooper).post(new Runnable() {
11262fb64a5cb160a2615f07ed669aa5738dbb74ad6cSvetoslav            @Override
11272fb64a5cb160a2615f07ed669aa5738dbb74ad6cSvetoslav            public void run() {
11282fb64a5cb160a2615f07ed669aa5738dbb74ad6cSvetoslav                mAdapterDeathObserver.onDied();
11292fb64a5cb160a2615f07ed669aa5738dbb74ad6cSvetoslav            }
11302fb64a5cb160a2615f07ed669aa5738dbb74ad6cSvetoslav        });
11312fb64a5cb160a2615f07ed669aa5738dbb74ad6cSvetoslav    }
11322fb64a5cb160a2615f07ed669aa5738dbb74ad6cSvetoslav
1133a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final class PrintDocumentAdapterObserver
1134a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            extends IPrintDocumentAdapterObserver.Stub {
1135a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final WeakReference<RemotePrintDocument> mWeakDocument;
1136a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1137a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public PrintDocumentAdapterObserver(RemotePrintDocument document) {
1138a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mWeakDocument = new WeakReference<>(document);
1139a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
1140a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1141a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        @Override
1142a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void onDestroy() {
1143a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            final RemotePrintDocument document = mWeakDocument.get();
1144a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (document != null) {
11454237c92d850b7fb0fa0be15df94e4d1689e353fcSvet Ganov                document.onPrintingAppDied();
1146a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1147a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
1148a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
1149a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav}
1150