[go: nahoru, domu]

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
19645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmannimport android.annotation.NonNull;
20a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.content.ContentResolver;
21a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.content.Context;
22a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.net.Uri;
23a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.os.AsyncTask;
24a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.os.Bundle;
25a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.os.Handler;
26a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.os.IBinder.DeathRecipient;
27a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.os.ICancellationSignal;
28a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.os.Looper;
29a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.os.Message;
30a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.os.ParcelFileDescriptor;
31a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.os.RemoteException;
32a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.print.ILayoutResultCallback;
33a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.print.IPrintDocumentAdapter;
34a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.print.IPrintDocumentAdapterObserver;
35a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.print.IWriteResultCallback;
36a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.print.PageRange;
37a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.print.PrintAttributes;
38a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.print.PrintDocumentAdapter;
39a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.print.PrintDocumentInfo;
40a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport android.util.Log;
41a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
42a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport com.android.printspooler.R;
43a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport com.android.printspooler.util.PageRangeUtils;
44a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
45a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport libcore.io.IoUtils;
46a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
47a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport java.io.File;
48a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport java.io.FileInputStream;
49a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport java.io.FileOutputStream;
50a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport java.io.IOException;
51a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport java.io.InputStream;
52a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport java.io.OutputStream;
53a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport java.lang.ref.WeakReference;
54a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavimport java.util.Arrays;
55a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
56a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslavpublic final class RemotePrintDocument {
57a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final String LOG_TAG = "RemotePrintDocument";
58a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
596f249835a4ff9e7e7e3ca0190b7ecf72e689656dSvetoslav    private static final boolean DEBUG = false;
60a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
61645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann    private static final long FORCE_CANCEL_TIMEOUT = 1000; // ms
62645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann
63a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final int STATE_INITIAL = 0;
64a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final int STATE_STARTED = 1;
65a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final int STATE_UPDATING = 2;
66a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final int STATE_UPDATED = 3;
67a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final int STATE_FAILED = 4;
68a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final int STATE_FINISHED = 5;
69a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final int STATE_CANCELING = 6;
70a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final int STATE_CANCELED = 7;
71a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final int STATE_DESTROYED = 8;
72a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
73a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private final Context mContext;
74a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
75a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private final RemotePrintDocumentInfo mDocumentInfo;
76a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private final UpdateSpec mUpdateSpec = new UpdateSpec();
77a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
78a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private final Looper mLooper;
79a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private final IPrintDocumentAdapter mPrintDocumentAdapter;
80e17123dd6d3666c88b47172b8efc995523b47346Svetoslav    private final RemoteAdapterDeathObserver mAdapterDeathObserver;
81a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
82a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private final UpdateResultCallbacks mUpdateCallbacks;
83a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
84a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private final CommandDoneCallback mCommandResultCallback =
85a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            new CommandDoneCallback() {
86a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        @Override
87a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void onDone() {
88a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (mCurrentCommand.isCompleted()) {
89a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (mCurrentCommand instanceof LayoutCommand) {
90a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    // If there is a next command after a layout is done, then another
91a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    // update was issued and the next command is another layout, so we
92a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    // do nothing. However, if there is no next command we may need to
93a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    // ask for some pages given we do not already have them or we do
94a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    // but the content has changed.
95a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    if (mNextCommand == null) {
96525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                        if (mUpdateSpec.pages != null && (mDocumentInfo.changed
97525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                                || (mDocumentInfo.info.getPageCount()
98525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                                        != PrintDocumentInfo.PAGE_COUNT_UNKNOWN
99525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                                && !PageRangeUtils.contains(mDocumentInfo.writtenPages,
100525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                                        mUpdateSpec.pages, mDocumentInfo.info.getPageCount())))) {
101a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            mNextCommand = new WriteCommand(mContext, mLooper,
102a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                                    mPrintDocumentAdapter, mDocumentInfo,
103a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                                    mDocumentInfo.info.getPageCount(), mUpdateSpec.pages,
104525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                                    mDocumentInfo.fileProvider, mCommandResultCallback);
105a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        } else {
106525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                            if (mUpdateSpec.pages != null) {
107525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                                // If we have the requested pages, update which ones to be printed.
108525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                                mDocumentInfo.printedPages = PageRangeUtils.computePrintedPages(
109525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                                        mUpdateSpec.pages, mDocumentInfo.writtenPages,
110525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                                        mDocumentInfo.info.getPageCount());
111525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                            }
112a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            // Notify we are done.
11305ff998fd86eff15e91694bc205ea0af0de83284Svet Ganov                            mState = STATE_UPDATED;
114a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            notifyUpdateCompleted();
115a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        }
116a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    }
117a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                } else {
118a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    // We always notify after a write.
11905ff998fd86eff15e91694bc205ea0af0de83284Svet Ganov                    mState = STATE_UPDATED;
120a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    notifyUpdateCompleted();
121a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
122a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                runPendingCommand();
123a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            } else if (mCurrentCommand.isFailed()) {
124a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mState = STATE_FAILED;
125a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                CharSequence error = mCurrentCommand.getError();
126a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mCurrentCommand = null;
127a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mNextCommand = null;
128a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mUpdateSpec.reset();
129a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                notifyUpdateFailed(error);
130a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            } else if (mCurrentCommand.isCanceled()) {
131a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (mState == STATE_CANCELING) {
132a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    mState = STATE_CANCELED;
133a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    notifyUpdateCanceled();
134a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
135a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                runPendingCommand();
136a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
137a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
138a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    };
139a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
140a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private final DeathRecipient mDeathRecipient = new DeathRecipient() {
141a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        @Override
142a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void binderDied() {
1434237c92d850b7fb0fa0be15df94e4d1689e353fcSvet Ganov            onPrintingAppDied();
144a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
145a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    };
146a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
147a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private int mState = STATE_INITIAL;
148a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
149a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private AsyncCommand mCurrentCommand;
150a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private AsyncCommand mNextCommand;
151a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
152e17123dd6d3666c88b47172b8efc995523b47346Svetoslav    public interface RemoteAdapterDeathObserver {
153e17123dd6d3666c88b47172b8efc995523b47346Svetoslav        public void onDied();
154a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
155a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
156a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public interface UpdateResultCallbacks {
157a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void onUpdateCompleted(RemotePrintDocumentInfo document);
158a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void onUpdateCanceled();
159a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void onUpdateFailed(CharSequence error);
160a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
161a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
162a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public RemotePrintDocument(Context context, IPrintDocumentAdapter adapter,
163e17123dd6d3666c88b47172b8efc995523b47346Svetoslav            MutexFileProvider fileProvider, RemoteAdapterDeathObserver deathObserver,
164525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            UpdateResultCallbacks callbacks) {
165a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mPrintDocumentAdapter = adapter;
166a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mLooper = context.getMainLooper();
167a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mContext = context;
168e17123dd6d3666c88b47172b8efc995523b47346Svetoslav        mAdapterDeathObserver = deathObserver;
169a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mDocumentInfo = new RemotePrintDocumentInfo();
170525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        mDocumentInfo.fileProvider = fileProvider;
171a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mUpdateCallbacks = callbacks;
172a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        connectToRemoteDocument();
173a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
174a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
175a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public void start() {
176a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (DEBUG) {
177a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.i(LOG_TAG, "[CALLED] start()");
178a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
179f6114c4f1ea92e740191b173515e1fdbc7450583Philip P. Moltmann        if (mState == STATE_FAILED) {
180f6114c4f1ea92e740191b173515e1fdbc7450583Philip P. Moltmann            Log.w(LOG_TAG, "Failed before start.");
1817134fcc07ca71cdb9eeccfc7d1846e4408849aecPhilip P. Moltmann        } else if (mState == STATE_DESTROYED) {
1827134fcc07ca71cdb9eeccfc7d1846e4408849aecPhilip P. Moltmann            Log.w(LOG_TAG, "Destroyed before start.");
183f6114c4f1ea92e740191b173515e1fdbc7450583Philip P. Moltmann        } else {
184f6114c4f1ea92e740191b173515e1fdbc7450583Philip P. Moltmann            if (mState != STATE_INITIAL) {
185f6114c4f1ea92e740191b173515e1fdbc7450583Philip P. Moltmann                throw new IllegalStateException("Cannot start in state:" + stateToString(mState));
186f6114c4f1ea92e740191b173515e1fdbc7450583Philip P. Moltmann            }
187f6114c4f1ea92e740191b173515e1fdbc7450583Philip P. Moltmann            try {
188f6114c4f1ea92e740191b173515e1fdbc7450583Philip P. Moltmann                mPrintDocumentAdapter.start();
189f6114c4f1ea92e740191b173515e1fdbc7450583Philip P. Moltmann                mState = STATE_STARTED;
190f6114c4f1ea92e740191b173515e1fdbc7450583Philip P. Moltmann            } catch (RemoteException re) {
191f6114c4f1ea92e740191b173515e1fdbc7450583Philip P. Moltmann                Log.e(LOG_TAG, "Error calling start()", re);
192f6114c4f1ea92e740191b173515e1fdbc7450583Philip P. Moltmann                mState = STATE_FAILED;
193f6114c4f1ea92e740191b173515e1fdbc7450583Philip P. Moltmann            }
194a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
195a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
196a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
197a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public boolean update(PrintAttributes attributes, PageRange[] pages, boolean preview) {
198a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        boolean willUpdate;
199a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
200a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (DEBUG) {
201a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.i(LOG_TAG, "[CALLED] update()");
202a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
203a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
204a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (hasUpdateError()) {
205a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            throw new IllegalStateException("Cannot update without a clearing the failure");
206a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
207a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
208a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (mState == STATE_INITIAL || mState == STATE_FINISHED || mState == STATE_DESTROYED) {
209a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            throw new IllegalStateException("Cannot update in state:" + stateToString(mState));
210a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
211a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
212a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        // We schedule a layout if the constraints changed.
213a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (!mUpdateSpec.hasSameConstraints(attributes, preview)) {
214a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            willUpdate = true;
215a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
216a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // If there is a current command that is running we ask for a
217a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // cancellation and start over.
218a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (mCurrentCommand != null && (mCurrentCommand.isRunning()
219a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    || mCurrentCommand.isPending())) {
220645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                mCurrentCommand.cancel(false);
221a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
222a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
223a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Schedule a layout command.
224a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            PrintAttributes oldAttributes = mDocumentInfo.attributes != null
225a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    ? mDocumentInfo.attributes : new PrintAttributes.Builder().build();
226a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            AsyncCommand command = new LayoutCommand(mLooper, mPrintDocumentAdapter,
227a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                  mDocumentInfo, oldAttributes, attributes, preview, mCommandResultCallback);
228a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            scheduleCommand(command);
229a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
230a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_UPDATING;
231a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        // If no layout in progress and we don't have all pages - schedule a write.
232a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        } else if ((!(mCurrentCommand instanceof LayoutCommand)
233a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                || (!mCurrentCommand.isPending() && !mCurrentCommand.isRunning()))
234525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                && pages != null && !PageRangeUtils.contains(mUpdateSpec.pages, pages,
235525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                mDocumentInfo.info.getPageCount())) {
236a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            willUpdate = true;
237a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
238a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Cancel the current write as a new one is to be scheduled.
239a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (mCurrentCommand instanceof WriteCommand
240a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    && (mCurrentCommand.isPending() || mCurrentCommand.isRunning())) {
241645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                mCurrentCommand.cancel(false);
242a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
243a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
244a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Schedule a write command.
245a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            AsyncCommand command = new WriteCommand(mContext, mLooper, mPrintDocumentAdapter,
246a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    mDocumentInfo, mDocumentInfo.info.getPageCount(), pages,
247525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                    mDocumentInfo.fileProvider, mCommandResultCallback);
248a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            scheduleCommand(command);
249a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
250a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_UPDATING;
251a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        } else {
252a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            willUpdate = false;
253a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (DEBUG) {
254a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Log.i(LOG_TAG, "[SKIPPING] No update needed");
255a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
256a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
257a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
258a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        // Keep track of what is requested.
259a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mUpdateSpec.update(attributes, preview, pages);
260a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
261a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        runPendingCommand();
262a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
263a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        return willUpdate;
264a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
265a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
266a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public void finish() {
267a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (DEBUG) {
268a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.i(LOG_TAG, "[CALLED] finish()");
269a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
270a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (mState != STATE_STARTED && mState != STATE_UPDATED
2719c9888b8c59e35717ecfc32e9b96fb8702ceb480Svetoslav                && mState != STATE_FAILED && mState != STATE_CANCELING
2727134fcc07ca71cdb9eeccfc7d1846e4408849aecPhilip P. Moltmann                && mState != STATE_CANCELED && mState != STATE_DESTROYED) {
273a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            throw new IllegalStateException("Cannot finish in state:"
274a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    + stateToString(mState));
275a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
276a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        try {
277a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mPrintDocumentAdapter.finish();
278a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_FINISHED;
279a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        } catch (RemoteException re) {
2804237c92d850b7fb0fa0be15df94e4d1689e353fcSvet Ganov            Log.e(LOG_TAG, "Error calling finish()");
281a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_FAILED;
282a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
283a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
284a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
285645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann    public void cancel(boolean force) {
286a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (DEBUG) {
287645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann            Log.i(LOG_TAG, "[CALLED] cancel(" + force + ")");
288a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
289a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
290cc3fa0d295ea39e412e4a7e0dd4c916b5123bca5Philip P. Moltmann        mNextCommand = null;
291a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
292a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (mState != STATE_UPDATING) {
293cc3fa0d295ea39e412e4a7e0dd4c916b5123bca5Philip P. Moltmann            return;
294a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
295a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
296a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mState = STATE_CANCELING;
297a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
298645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann        mCurrentCommand.cancel(force);
299a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
300a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
301a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public void destroy() {
302a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (DEBUG) {
303a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.i(LOG_TAG, "[CALLED] destroy()");
304a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
305a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (mState == STATE_DESTROYED) {
306a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            throw new IllegalStateException("Cannot destroy in state:" + stateToString(mState));
307a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
308a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
309a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mState = STATE_DESTROYED;
310a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
311a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        disconnectFromRemoteDocument();
312a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
313a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
314fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov    public void kill(String reason) {
315fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov        if (DEBUG) {
316fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov            Log.i(LOG_TAG, "[CALLED] kill()");
317fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov        }
318fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov
319fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov        try {
320fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov            mPrintDocumentAdapter.kill(reason);
321fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov        } catch (RemoteException re) {
322fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov            Log.e(LOG_TAG, "Error calling kill()", re);
323fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov        }
324fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov    }
325fce84f035c35606c5707e735f503f7bdcfd5b2a1Svet Ganov
326a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public boolean isUpdating() {
327a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        return mState == STATE_UPDATING || mState == STATE_CANCELING;
328a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
329a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
330a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public boolean isDestroyed() {
331a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        return mState == STATE_DESTROYED;
332a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
333a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
334a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public boolean hasUpdateError() {
335a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        return mState == STATE_FAILED;
336a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
337a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
3386552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav    public boolean hasLaidOutPages() {
3396552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav        return mDocumentInfo.info != null
3406552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav                && mDocumentInfo.info.getPageCount() > 0;
3416552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav    }
3426552bf3da60159607d9266eb295ee3c448f6c3deSvetoslav
343a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public void clearUpdateError() {
344a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (!hasUpdateError()) {
345a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            throw new IllegalStateException("No update error to clear");
346a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
347a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mState = STATE_STARTED;
348a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
349a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
350a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public RemotePrintDocumentInfo getDocumentInfo() {
351a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        return mDocumentInfo;
352a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
353a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
354a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public void writeContent(ContentResolver contentResolver, Uri uri) {
355525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        File file = null;
356a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        InputStream in = null;
357a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        OutputStream out = null;
358a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        try {
359525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            file = mDocumentInfo.fileProvider.acquireFile(null);
360525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            in = new FileInputStream(file);
361a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            out = contentResolver.openOutputStream(uri);
362a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            final byte[] buffer = new byte[8192];
363a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            while (true) {
364a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                final int readByteCount = in.read(buffer);
365a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (readByteCount < 0) {
366a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    break;
367a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
368a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                out.write(buffer, 0, readByteCount);
369a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
370a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        } catch (IOException e) {
371a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.e(LOG_TAG, "Error writing document content.", e);
372a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        } finally {
373a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            IoUtils.closeQuietly(in);
374a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            IoUtils.closeQuietly(out);
375525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            if (file != null) {
376525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                mDocumentInfo.fileProvider.releaseFile();
377525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            }
378a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
379a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
380a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
381a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private void notifyUpdateCanceled() {
382a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (DEBUG) {
383a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.i(LOG_TAG, "[CALLING] onUpdateCanceled()");
384a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
385a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mUpdateCallbacks.onUpdateCanceled();
386a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
387a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
388a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private void notifyUpdateCompleted() {
389a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (DEBUG) {
390a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.i(LOG_TAG, "[CALLING] onUpdateCompleted()");
391a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
392a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mUpdateCallbacks.onUpdateCompleted(mDocumentInfo);
393a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
394a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
395a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private void notifyUpdateFailed(CharSequence error) {
396a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (DEBUG) {
397a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.i(LOG_TAG, "[CALLING] onUpdateCompleted()");
398a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
399a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mUpdateCallbacks.onUpdateFailed(error);
400a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
401a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
402a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private void connectToRemoteDocument() {
403a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        try {
404a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mPrintDocumentAdapter.asBinder().linkToDeath(mDeathRecipient, 0);
405a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        } catch (RemoteException re) {
406a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.w(LOG_TAG, "The printing process is dead.");
407a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            destroy();
408a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return;
409a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
410a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
411a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        try {
412a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mPrintDocumentAdapter.setObserver(new PrintDocumentAdapterObserver(this));
413a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        } catch (RemoteException re) {
414a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.w(LOG_TAG, "Error setting observer to the print adapter.");
415a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            destroy();
416a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
417a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
418a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
419a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private void disconnectFromRemoteDocument() {
420a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        try {
421a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mPrintDocumentAdapter.setObserver(null);
422a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        } catch (RemoteException re) {
423a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            Log.w(LOG_TAG, "Error setting observer to the print adapter.");
424a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Keep going - best effort...
425a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
426a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
427a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        mPrintDocumentAdapter.asBinder().unlinkToDeath(mDeathRecipient, 0);
428a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
429a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
430a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private void scheduleCommand(AsyncCommand command) {
431a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (mCurrentCommand == null) {
432a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mCurrentCommand = command;
433a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        } else {
434a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mNextCommand = command;
435a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
436a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
437a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
438a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private void runPendingCommand() {
439a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (mCurrentCommand != null
440a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                && (mCurrentCommand.isCompleted()
441a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        || mCurrentCommand.isCanceled())) {
442a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mCurrentCommand = mNextCommand;
443a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mNextCommand = null;
444a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
445a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
446a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        if (mCurrentCommand != null) {
447a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (mCurrentCommand.isPending()) {
448a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mCurrentCommand.run();
449645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann
450645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                mState = STATE_UPDATING;
451a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
452a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        } else {
453a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_UPDATED;
454a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
455a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
456a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
457a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static String stateToString(int state) {
458a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        switch (state) {
459a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            case STATE_FINISHED: {
460a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return "STATE_FINISHED";
461a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
462a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            case STATE_FAILED: {
463a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return "STATE_FAILED";
464a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
465a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            case STATE_STARTED: {
466a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return "STATE_STARTED";
467a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
468a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            case STATE_UPDATING: {
469a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return "STATE_UPDATING";
470a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
471a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            case STATE_UPDATED: {
472a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return "STATE_UPDATED";
473a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
474a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            case STATE_CANCELING: {
475a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return "STATE_CANCELING";
476a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
477a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            case STATE_CANCELED: {
478a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return "STATE_CANCELED";
479a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
480a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            case STATE_DESTROYED: {
481a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return "STATE_DESTROYED";
482a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
483a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            default: {
484a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return "STATE_UNKNOWN";
485a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
486a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
487a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
488a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
489a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    static final class UpdateSpec {
490a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        final PrintAttributes attributes = new PrintAttributes.Builder().build();
491a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        boolean preview;
492a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        PageRange[] pages;
493a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
494a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void update(PrintAttributes attributes, boolean preview,
495a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                PageRange[] pages) {
496a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            this.attributes.copyFrom(attributes);
497a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            this.preview = preview;
498525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            this.pages = (pages != null) ? Arrays.copyOf(pages, pages.length) : null;
499a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
500a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
501a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void reset() {
502a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            attributes.clear();
503a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            preview = false;
504a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            pages = null;
505a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
506a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
507a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public boolean hasSameConstraints(PrintAttributes attributes, boolean preview) {
508a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return this.attributes.equals(attributes) && this.preview == preview;
509a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
510a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
511a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
512a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    public static final class RemotePrintDocumentInfo {
513a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public PrintAttributes attributes;
514a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public Bundle metadata;
515a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public PrintDocumentInfo info;
516a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public PageRange[] printedPages;
517a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public PageRange[] writtenPages;
518525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        public MutexFileProvider fileProvider;
519525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        public boolean changed;
520525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        public boolean updated;
521525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        public boolean laidout;
522a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
523a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
524a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private interface CommandDoneCallback {
525a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void onDone();
526a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
527a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
528a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static abstract class AsyncCommand implements Runnable {
529a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private static final int STATE_PENDING = 0;
530a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private static final int STATE_RUNNING = 1;
531a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private static final int STATE_COMPLETED = 2;
532a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private static final int STATE_CANCELED = 3;
533a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private static final int STATE_CANCELING = 4;
534a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private static final int STATE_FAILED = 5;
535a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
536a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private static int sSequenceCounter;
537a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
538a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected final int mSequence = sSequenceCounter++;
539a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected final IPrintDocumentAdapter mAdapter;
540a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected final RemotePrintDocumentInfo mDocument;
541a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
542a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected final CommandDoneCallback mDoneCallback;
543a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
544645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann        private final Handler mHandler;
545645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann
546a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected ICancellationSignal mCancellation;
547a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
548a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private CharSequence mError;
549a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
550a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private int mState = STATE_PENDING;
551a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
552645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann        public AsyncCommand(Looper looper, IPrintDocumentAdapter adapter, RemotePrintDocumentInfo document,
553a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                CommandDoneCallback doneCallback) {
554645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann            mHandler = new AsyncCommandHandler(looper);
555a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mAdapter = adapter;
556a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mDocument = document;
557a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mDoneCallback = doneCallback;
558a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
559a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
560a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected final boolean isCanceling() {
561a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return mState == STATE_CANCELING;
562a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
563a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
564a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public final boolean isCanceled() {
565a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return mState == STATE_CANCELED;
566a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
567a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
568645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann        /**
569645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann         * If a force cancel is pending, remove it. This is usually called when a command returns
570645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann         * and thereby does not need to be canceled anymore.
571645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann         */
572645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann        protected void removeForceCancel() {
573645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann            if (DEBUG) {
574645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                if (mHandler.hasMessages(AsyncCommandHandler.MSG_FORCE_CANCEL)) {
575645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                    Log.i(LOG_TAG, "[FORCE CANCEL] Removed");
576645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                }
577645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann            }
578645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann
579645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann            mHandler.removeMessages(AsyncCommandHandler.MSG_FORCE_CANCEL);
580645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann        }
581645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann
582645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann        /**
583645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann         * Cancel the current command.
584645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann         *
585645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann         * @param force If set, does not wait for the {@link PrintDocumentAdapter} to cancel. This
586645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann         *              should only be used if this is the last command send to the as otherwise the
587645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann         *              {@link PrintDocumentAdapter adapter} might get commands while it is still
588645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann         *              running the old one.
589645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann         */
590645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann        public final void cancel(boolean force) {
591a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (isRunning()) {
592a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                canceling();
593a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (mCancellation != null) {
594a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    try {
595a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        mCancellation.cancel();
596a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } catch (RemoteException re) {
597a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        Log.w(LOG_TAG, "Error while canceling", re);
598a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    }
599a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
600645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann            }
601645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann
602645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann            if (isCanceling()) {
603645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                if (force) {
604645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                    if (DEBUG) {
605645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                        Log.i(LOG_TAG, "[FORCE CANCEL] queued");
606645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                    }
607645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                    mHandler.sendMessageDelayed(
608645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                            mHandler.obtainMessage(AsyncCommandHandler.MSG_FORCE_CANCEL),
609645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                            FORCE_CANCEL_TIMEOUT);
610645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                }
611a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
612645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                return;
613a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
614645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann
615645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann            canceled();
616645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann
617645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann            // Done.
618645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann            mDoneCallback.onDone();
619a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
620a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
621a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected final void canceling() {
622a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (mState != STATE_PENDING && mState != STATE_RUNNING) {
623a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                throw new IllegalStateException("Command not pending or running.");
624a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
625a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_CANCELING;
626a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
627a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
628a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected final void canceled() {
629a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (mState != STATE_CANCELING) {
630a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                throw new IllegalStateException("Not canceling.");
631a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
632a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_CANCELED;
633a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
634a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
635a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public final boolean isPending() {
636a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return mState == STATE_PENDING;
637a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
638a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
639a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected final void running() {
640a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (mState != STATE_PENDING) {
641a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                throw new IllegalStateException("Not pending.");
642a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
643a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_RUNNING;
644a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
645a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
646a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public final boolean isRunning() {
647a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return mState == STATE_RUNNING;
648a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
649a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
650a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected final void completed() {
651a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (mState != STATE_RUNNING && mState != STATE_CANCELING) {
652a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                throw new IllegalStateException("Not running.");
653a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
654a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_COMPLETED;
655a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
656a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
657a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public final boolean isCompleted() {
658a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return mState == STATE_COMPLETED;
659a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
660a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
661a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        protected final void failed(CharSequence error) {
662645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann            if (mState != STATE_RUNNING && mState != STATE_CANCELING) {
663a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                throw new IllegalStateException("Not running.");
664a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
665a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mState = STATE_FAILED;
666a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
667a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mError = error;
668a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
669a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
670a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public final boolean isFailed() {
671a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return mState == STATE_FAILED;
672a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
673a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
674a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public CharSequence getError() {
675a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return mError;
676a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
677645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann
678645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann        /**
679645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann         * Handler for the async command.
680645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann         */
681645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann        private class AsyncCommandHandler extends Handler {
682645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann            /** Message indicated the desire for to force cancel a command */
683645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann            final static int MSG_FORCE_CANCEL = 0;
684645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann
685645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann            AsyncCommandHandler(@NonNull Looper looper) {
686645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                super(looper);
687645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann            }
688645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann
689645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann            @Override
690645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann            public void handleMessage(Message msg) {
691645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                switch (msg.what) {
692645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                    case MSG_FORCE_CANCEL:
693645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                        if (isCanceling()) {
694645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                            if (DEBUG) {
695645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                                Log.i(LOG_TAG, "[FORCE CANCEL] executed");
696645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                            }
697645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                            failed("Command did not respond to cancellation in "
698645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                                    + FORCE_CANCEL_TIMEOUT + " ms");
699645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann
700645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                            mDoneCallback.onDone();
701645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                        }
702645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                        break;
703645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                    default:
704645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                        // not reached;
705645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                }
706645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann            }
707645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann        }
708a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
709a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
710a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final class LayoutCommand extends AsyncCommand {
711a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final PrintAttributes mOldAttributes = new PrintAttributes.Builder().build();
712a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final PrintAttributes mNewAttributes = new PrintAttributes.Builder().build();
713a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final Bundle mMetadata = new Bundle();
714a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
715a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final ILayoutResultCallback mRemoteResultCallback;
716a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
717a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final Handler mHandler;
718a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
719a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public LayoutCommand(Looper looper, IPrintDocumentAdapter adapter,
720a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                RemotePrintDocumentInfo document, PrintAttributes oldAttributes,
721a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                PrintAttributes newAttributes, boolean preview, CommandDoneCallback callback) {
722645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann            super(looper, adapter, document, callback);
723a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mHandler = new LayoutHandler(looper);
724a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mRemoteResultCallback = new LayoutResultCallback(mHandler);
725a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mOldAttributes.copyFrom(oldAttributes);
726a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mNewAttributes.copyFrom(newAttributes);
727a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mMetadata.putBoolean(PrintDocumentAdapter.EXTRA_PRINT_PREVIEW, preview);
728a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
729a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
730a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        @Override
731a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void run() {
732a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            running();
733a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
734a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            try {
735a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (DEBUG) {
736a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    Log.i(LOG_TAG, "[PERFORMING] layout");
737a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
738525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                mDocument.changed = false;
739a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mAdapter.layout(mOldAttributes, mNewAttributes, mRemoteResultCallback,
740a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        mMetadata, mSequence);
741a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            } catch (RemoteException re) {
742a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Log.e(LOG_TAG, "Error calling layout", re);
743a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                handleOnLayoutFailed(null, mSequence);
744a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
745a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
746a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
747a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private void handleOnLayoutStarted(ICancellationSignal cancellation, int sequence) {
748a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (sequence != mSequence) {
749a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return;
750a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
751a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
752a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (DEBUG) {
753a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Log.i(LOG_TAG, "[CALLBACK] onLayoutStarted");
754a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
755a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
756a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (isCanceling()) {
757a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                try {
758a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    cancellation.cancel();
759a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                } catch (RemoteException re) {
760a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    Log.e(LOG_TAG, "Error cancelling", re);
761a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    handleOnLayoutFailed(null, mSequence);
762a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
763a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            } else {
764a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mCancellation = cancellation;
765a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
766a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
767a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
768a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private void handleOnLayoutFinished(PrintDocumentInfo info,
769a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                boolean changed, int sequence) {
770a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (sequence != mSequence) {
771a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return;
772a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
773a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
774a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (DEBUG) {
775a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Log.i(LOG_TAG, "[CALLBACK] onLayoutFinished");
776a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
777a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
778a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            completed();
779a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
780a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // If the document description changed or the content in the
781a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // document changed, the we need to invalidate the pages.
782a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (changed || !equalsIgnoreSize(mDocument.info, info)) {
783a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                // If the content changed we throw away all pages as
784a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                // we will request them again with the new content.
785a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mDocument.writtenPages = null;
786a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mDocument.printedPages = null;
787525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                mDocument.changed = true;
788a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
789a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
790a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Update the document with data from the layout pass.
791a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mDocument.attributes = mNewAttributes;
792a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mDocument.metadata = mMetadata;
793525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            mDocument.laidout = true;
794a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mDocument.info = info;
795a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
796a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Release the remote cancellation interface.
797a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mCancellation = null;
798a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
799a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Done.
800a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mDoneCallback.onDone();
801a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
802a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
803a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private void handleOnLayoutFailed(CharSequence error, int sequence) {
804a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (sequence != mSequence) {
805a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return;
806a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
807a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
808a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (DEBUG) {
809a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Log.i(LOG_TAG, "[CALLBACK] onLayoutFailed");
810a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
811a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
812525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            mDocument.laidout = false;
813525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov
814a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            failed(error);
815a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
816a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Release the remote cancellation interface.
817a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mCancellation = null;
818a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
819a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Failed.
820a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mDoneCallback.onDone();
821a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
822a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
823a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private void handleOnLayoutCanceled(int sequence) {
824a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (sequence != mSequence) {
825a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return;
826a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
827a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
828a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (DEBUG) {
829a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Log.i(LOG_TAG, "[CALLBACK] onLayoutCanceled");
830a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
831a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
832a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            canceled();
833a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
834a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Release the remote cancellation interface.
835a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mCancellation = null;
836a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
837a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Done.
838a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mDoneCallback.onDone();
839a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
840a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
841a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private boolean equalsIgnoreSize(PrintDocumentInfo lhs, PrintDocumentInfo rhs) {
842a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (lhs == rhs) {
843a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return true;
844a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
845a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (lhs == null) {
846a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return false;
847a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            } else {
848a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (rhs == null) {
849a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    return false;
850a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
851a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (lhs.getContentType() != rhs.getContentType()
852a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        || lhs.getPageCount() != rhs.getPageCount()) {
853a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    return false;
854a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
855a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
856a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            return true;
857a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
858a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
859a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final class LayoutHandler extends Handler {
860a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public static final int MSG_ON_LAYOUT_STARTED = 1;
861a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public static final int MSG_ON_LAYOUT_FINISHED = 2;
862a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public static final int MSG_ON_LAYOUT_FAILED = 3;
863a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public static final int MSG_ON_LAYOUT_CANCELED = 4;
864a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
865a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public LayoutHandler(Looper looper) {
866a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                super(looper, null, false);
867a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
868a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
869a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            @Override
870a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public void handleMessage(Message message) {
871645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                // The command might have been force canceled, see
872645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                // AsyncCommand.AsyncCommandHandler#handleMessage
873645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                if (isFailed()) {
874645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                    if (DEBUG) {
87527db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                        Log.i(LOG_TAG, "[CALLBACK] on failed layout command");
876645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                    }
877645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann
878645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                    return;
87927db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                }
88027db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann
88127db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                int sequence;
88227db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                int what = message.what;
88327db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                switch (what) {
88427db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                    case MSG_ON_LAYOUT_FINISHED:
885645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                        removeForceCancel();
88627db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                        sequence = message.arg2;
88727db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                        break;
88827db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                    case MSG_ON_LAYOUT_FAILED:
88927db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                    case MSG_ON_LAYOUT_CANCELED:
89027db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                        removeForceCancel();
89127db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                        // $FALL-THROUGH - message uses the same format as "started"
89227db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                    case MSG_ON_LAYOUT_STARTED:
89327db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                        // Don't remote force-cancel as command is still running and might need to
89427db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                        // be canceled later
89527db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                        sequence = message.arg1;
89627db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                        break;
89727db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                    default:
89827db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                        // not reached
89927db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                        sequence = -1;
90027db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                }
90127db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann
90227db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                // If we are canceling any result is treated as a cancel
90327db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                if (isCanceling() && what != MSG_ON_LAYOUT_STARTED) {
90427db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                    what = MSG_ON_LAYOUT_CANCELED;
905645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                }
906645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann
90727db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                switch (what) {
908a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    case MSG_ON_LAYOUT_STARTED: {
909a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        ICancellationSignal cancellation = (ICancellationSignal) message.obj;
910a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        handleOnLayoutStarted(cancellation, sequence);
911a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } break;
912a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
913a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    case MSG_ON_LAYOUT_FINISHED: {
914a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        PrintDocumentInfo info = (PrintDocumentInfo) message.obj;
915a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        final boolean changed = (message.arg1 == 1);
916a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        handleOnLayoutFinished(info, changed, sequence);
917a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } break;
918a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
919a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    case MSG_ON_LAYOUT_FAILED: {
920a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        CharSequence error = (CharSequence) message.obj;
921a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        handleOnLayoutFailed(error, sequence);
922a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } break;
923a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
924a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    case MSG_ON_LAYOUT_CANCELED: {
925a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        handleOnLayoutCanceled(sequence);
926a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } break;
927a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
928a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
929a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
930a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
931a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private static final class LayoutResultCallback extends ILayoutResultCallback.Stub {
932a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            private final WeakReference<Handler> mWeakHandler;
933a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
934a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public LayoutResultCallback(Handler handler) {
935a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mWeakHandler = new WeakReference<>(handler);
936a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
937a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
938a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            @Override
939a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public void onLayoutStarted(ICancellationSignal cancellation, int sequence) {
940a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Handler handler = mWeakHandler.get();
941a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (handler != null) {
942a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    handler.obtainMessage(LayoutHandler.MSG_ON_LAYOUT_STARTED,
943a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            sequence, 0, cancellation).sendToTarget();
944a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
945a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
946a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
947a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            @Override
948a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public void onLayoutFinished(PrintDocumentInfo info, boolean changed, int sequence) {
949a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Handler handler = mWeakHandler.get();
950a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (handler != null) {
951a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    handler.obtainMessage(LayoutHandler.MSG_ON_LAYOUT_FINISHED,
952a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            changed ? 1 : 0, sequence, info).sendToTarget();
953a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
954a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
955a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
956a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            @Override
957a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public void onLayoutFailed(CharSequence error, int sequence) {
958a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Handler handler = mWeakHandler.get();
959a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (handler != null) {
960a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    handler.obtainMessage(LayoutHandler.MSG_ON_LAYOUT_FAILED,
961a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            sequence, 0, error).sendToTarget();
962a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
963a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
964a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
965a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            @Override
966a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public void onLayoutCanceled(int sequence) {
967a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Handler handler = mWeakHandler.get();
968a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (handler != null) {
969a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    handler.obtainMessage(LayoutHandler.MSG_ON_LAYOUT_CANCELED,
970a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            sequence, 0).sendToTarget();
971a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
972a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
973a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
974a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
975a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
976a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final class WriteCommand extends AsyncCommand {
977a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final int mPageCount;
978a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final PageRange[] mPages;
979525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov        private final MutexFileProvider mFileProvider;
980a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
981a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final IWriteResultCallback mRemoteResultCallback;
982c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann        private final CommandDoneCallback mWriteDoneCallback;
983a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
984a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final Context mContext;
985a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final Handler mHandler;
986a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
987a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public WriteCommand(Context context, Looper looper, IPrintDocumentAdapter adapter,
988a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                RemotePrintDocumentInfo document, int pageCount, PageRange[] pages,
989525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                MutexFileProvider fileProvider, CommandDoneCallback callback) {
990645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann            super(looper, adapter, document, callback);
991a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mContext = context;
992a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mHandler = new WriteHandler(looper);
993a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mRemoteResultCallback = new WriteResultCallback(mHandler);
994a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mPageCount = pageCount;
995a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mPages = Arrays.copyOf(pages, pages.length);
996525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            mFileProvider = fileProvider;
997c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann            mWriteDoneCallback = callback;
998a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
999a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1000a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        @Override
1001a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void run() {
1002a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            running();
1003a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1004a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // This is a long running operation as we will be reading fully
1005a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // the written data. In case of a cancellation, we ask the client
1006a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // to stop writing data and close the file descriptor after
1007a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // which we will reach the end of the stream, thus stop reading.
1008a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            new AsyncTask<Void, Void, Void>() {
1009a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                @Override
1010a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                protected Void doInBackground(Void... params) {
1011525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                    File file = null;
1012a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    InputStream in = null;
1013a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    OutputStream out = null;
1014a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    ParcelFileDescriptor source = null;
1015a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    ParcelFileDescriptor sink = null;
1016a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    try {
1017525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                        file = mFileProvider.acquireFile(null);
1018a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
1019a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        source = pipe[0];
1020a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        sink = pipe[1];
1021a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1022a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        in = new FileInputStream(source.getFileDescriptor());
1023525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                        out = new FileOutputStream(file);
1024a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1025a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        // Async call to initiate the other process writing the data.
1026a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        if (DEBUG) {
1027a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            Log.i(LOG_TAG, "[PERFORMING] write");
1028a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        }
1029a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        mAdapter.write(mPages, sink, mRemoteResultCallback, mSequence);
1030a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1031a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        // Close the source. It is now held by the client.
1032a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        sink.close();
1033a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        sink = null;
1034a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1035a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        // Read the data.
1036a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        final byte[] buffer = new byte[8192];
1037a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        while (true) {
1038a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            final int readByteCount = in.read(buffer);
1039a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            if (readByteCount < 0) {
1040a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                                break;
1041a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            }
1042a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            out.write(buffer, 0, readByteCount);
1043a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        }
1044a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } catch (RemoteException | IOException e) {
1045a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        Log.e(LOG_TAG, "Error calling write()", e);
1046a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } finally {
1047a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        IoUtils.closeQuietly(in);
1048a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        IoUtils.closeQuietly(out);
1049a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        IoUtils.closeQuietly(sink);
1050a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        IoUtils.closeQuietly(source);
1051525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                        if (file != null) {
1052525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                            mFileProvider.releaseFile();
1053525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                        }
1054a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    }
1055a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    return null;
1056a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
1057a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
1058a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
1059a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1060a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private void handleOnWriteStarted(ICancellationSignal cancellation, int sequence) {
1061a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (sequence != mSequence) {
1062a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return;
1063a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1064a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1065a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (DEBUG) {
1066a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Log.i(LOG_TAG, "[CALLBACK] onWriteStarted");
1067a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1068a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1069a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (isCanceling()) {
1070a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                try {
1071a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    cancellation.cancel();
1072a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                } catch (RemoteException re) {
1073a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    Log.e(LOG_TAG, "Error cancelling", re);
1074a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    handleOnWriteFailed(null, sequence);
1075a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
1076a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            } else {
1077a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mCancellation = cancellation;
1078a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1079a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
1080a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1081a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private void handleOnWriteFinished(PageRange[] pages, int sequence) {
1082a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (sequence != mSequence) {
1083a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return;
1084a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1085a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1086a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (DEBUG) {
1087a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Log.i(LOG_TAG, "[CALLBACK] onWriteFinished");
1088a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1089a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1090a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            PageRange[] writtenPages = PageRangeUtils.normalize(pages);
1091525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov            PageRange[] printedPages = PageRangeUtils.computePrintedPages(
1092525a66b2bb5abf844aff2109bdc9ed819566beceSvet Ganov                    mPages, writtenPages, mPageCount);
1093a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1094a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Handle if we got invalid pages
1095a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (printedPages != null) {
1096a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mDocument.writtenPages = writtenPages;
1097a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mDocument.printedPages = printedPages;
1098a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                completed();
1099a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            } else {
1100a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mDocument.writtenPages = null;
1101a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mDocument.printedPages = null;
1102a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                failed(mContext.getString(R.string.print_error_default_message));
1103a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1104a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1105a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Release the remote cancellation interface.
1106a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mCancellation = null;
1107a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1108a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Done.
1109c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann            mWriteDoneCallback.onDone();
1110a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
1111a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1112a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private void handleOnWriteFailed(CharSequence error, int sequence) {
1113a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (sequence != mSequence) {
1114a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return;
1115a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1116a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1117a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (DEBUG) {
1118a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Log.i(LOG_TAG, "[CALLBACK] onWriteFailed");
1119a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1120a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1121a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            failed(error);
1122a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1123a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Release the remote cancellation interface.
1124a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mCancellation = null;
1125a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1126a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Done.
1127c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann            mWriteDoneCallback.onDone();
1128a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
1129a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1130a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private void handleOnWriteCanceled(int sequence) {
1131a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (sequence != mSequence) {
1132a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                return;
1133a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1134a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1135a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (DEBUG) {
1136a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Log.i(LOG_TAG, "[CALLBACK] onWriteCanceled");
1137a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1138a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1139a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            canceled();
1140a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1141a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Release the remote cancellation interface.
1142a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mCancellation = null;
1143a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1144a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            // Done.
1145c43639c3067dda5df189fb3cbf14f256c17e677dPhilip P. Moltmann            mWriteDoneCallback.onDone();
1146a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
1147a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1148a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final class WriteHandler extends Handler {
1149a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public static final int MSG_ON_WRITE_STARTED = 1;
1150a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public static final int MSG_ON_WRITE_FINISHED = 2;
1151a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public static final int MSG_ON_WRITE_FAILED = 3;
1152a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public static final int MSG_ON_WRITE_CANCELED = 4;
1153a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1154a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public WriteHandler(Looper looper) {
1155a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                super(looper, null, false);
1156a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1157a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1158a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            @Override
1159a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public void handleMessage(Message message) {
1160645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                // The command might have been force canceled, see
1161645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                // AsyncCommand.AsyncCommandHandler#handleMessage
1162645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                if (isFailed()) {
1163645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                    if (DEBUG) {
116427db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                        Log.i(LOG_TAG, "[CALLBACK] on failed write command");
1165645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                    }
1166645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann
1167645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                    return;
116827db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                }
116927db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann
117027db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                int what = message.what;
117127db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                switch (what) {
117227db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                    case MSG_ON_WRITE_FINISHED:
117327db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                    case MSG_ON_WRITE_FAILED:
117427db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                    case MSG_ON_WRITE_CANCELED:
1175645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                        removeForceCancel();
117627db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                    case MSG_ON_WRITE_STARTED:
117727db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                        // Don't remote force-cancel as command is still running and might need to
117827db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                        // be canceled later
117927db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                        break;
118027db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                }
118127db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann
118227db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                // If we are canceling any result is treated as a cancel
118327db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                if (isCanceling() && what != MSG_ON_WRITE_STARTED) {
118427db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                    what = MSG_ON_WRITE_CANCELED;
1185645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann                }
1186645a3e1ca6ce26da52fa158ca159a31bd38de77dPhilip P. Moltmann
118727db6611a76a11a5d271dd824167fa1d4b23f944Philip P. Moltmann                switch (what) {
1188a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    case MSG_ON_WRITE_STARTED: {
1189a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        ICancellationSignal cancellation = (ICancellationSignal) message.obj;
1190a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        final int sequence = message.arg1;
1191a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        handleOnWriteStarted(cancellation, sequence);
1192a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } break;
1193a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1194a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    case MSG_ON_WRITE_FINISHED: {
1195a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        PageRange[] pages = (PageRange[]) message.obj;
1196a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        final int sequence = message.arg1;
1197a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        handleOnWriteFinished(pages, sequence);
1198a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } break;
1199a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1200a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    case MSG_ON_WRITE_FAILED: {
1201a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        CharSequence error = (CharSequence) message.obj;
1202a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        final int sequence = message.arg1;
1203a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        handleOnWriteFailed(error, sequence);
1204a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } break;
1205a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1206a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    case MSG_ON_WRITE_CANCELED: {
1207a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        final int sequence = message.arg1;
1208a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        handleOnWriteCanceled(sequence);
1209a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    } break;
1210a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
1211a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1212a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
1213a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1214a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private static final class WriteResultCallback extends IWriteResultCallback.Stub {
1215a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            private final WeakReference<Handler> mWeakHandler;
1216a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1217a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public WriteResultCallback(Handler handler) {
1218a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                mWeakHandler = new WeakReference<>(handler);
1219a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1220a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1221a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            @Override
1222a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public void onWriteStarted(ICancellationSignal cancellation, int sequence) {
1223a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Handler handler = mWeakHandler.get();
1224a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (handler != null) {
1225a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    handler.obtainMessage(WriteHandler.MSG_ON_WRITE_STARTED,
1226a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            sequence, 0, cancellation).sendToTarget();
1227a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
1228a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1229a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1230a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            @Override
1231a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public void onWriteFinished(PageRange[] pages, int sequence) {
1232a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Handler handler = mWeakHandler.get();
1233a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (handler != null) {
1234a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    handler.obtainMessage(WriteHandler.MSG_ON_WRITE_FINISHED,
1235a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                            sequence, 0, pages).sendToTarget();
1236a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
1237a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1238a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1239a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            @Override
1240a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public void onWriteFailed(CharSequence error, int sequence) {
1241a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Handler handler = mWeakHandler.get();
1242a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (handler != null) {
1243a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    handler.obtainMessage(WriteHandler.MSG_ON_WRITE_FAILED,
1244a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        sequence, 0, error).sendToTarget();
1245a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
1246a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1247a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1248a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            @Override
1249a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            public void onWriteCanceled(int sequence) {
1250a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                Handler handler = mWeakHandler.get();
1251a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                if (handler != null) {
1252a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                    handler.obtainMessage(WriteHandler.MSG_ON_WRITE_CANCELED,
1253a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                        sequence, 0).sendToTarget();
1254a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav                }
1255a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1256a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
1257a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
1258a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
12594237c92d850b7fb0fa0be15df94e4d1689e353fcSvet Ganov    private void onPrintingAppDied() {
12604237c92d850b7fb0fa0be15df94e4d1689e353fcSvet Ganov        mState = STATE_FAILED;
12612fb64a5cb160a2615f07ed669aa5738dbb74ad6cSvetoslav        new Handler(mLooper).post(new Runnable() {
12622fb64a5cb160a2615f07ed669aa5738dbb74ad6cSvetoslav            @Override
12632fb64a5cb160a2615f07ed669aa5738dbb74ad6cSvetoslav            public void run() {
12642fb64a5cb160a2615f07ed669aa5738dbb74ad6cSvetoslav                mAdapterDeathObserver.onDied();
12652fb64a5cb160a2615f07ed669aa5738dbb74ad6cSvetoslav            }
12662fb64a5cb160a2615f07ed669aa5738dbb74ad6cSvetoslav        });
12672fb64a5cb160a2615f07ed669aa5738dbb74ad6cSvetoslav    }
12682fb64a5cb160a2615f07ed669aa5738dbb74ad6cSvetoslav
1269a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    private static final class PrintDocumentAdapterObserver
1270a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            extends IPrintDocumentAdapterObserver.Stub {
1271a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        private final WeakReference<RemotePrintDocument> mWeakDocument;
1272a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1273a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public PrintDocumentAdapterObserver(RemotePrintDocument document) {
1274a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            mWeakDocument = new WeakReference<>(document);
1275a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
1276a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav
1277a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        @Override
1278a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        public void onDestroy() {
1279a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            final RemotePrintDocument document = mWeakDocument.get();
1280a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            if (document != null) {
12814237c92d850b7fb0fa0be15df94e4d1689e353fcSvet Ganov                document.onPrintingAppDied();
1282a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav            }
1283a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav        }
1284a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav    }
1285a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav}
1286