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