/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.printspooler.ui;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.app.LoaderManager;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.Loader;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.database.DataSetObserver;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.print.IPrintDocumentAdapter;
import android.print.PageRange;
import android.print.PrintAttributes;
import android.print.PrintAttributes.MediaSize;
import android.print.PrintAttributes.Resolution;
import android.print.PrintDocumentInfo;
import android.print.PrintJobInfo;
import android.print.PrintManager;
import android.print.PrintServicesLoader;
import android.print.PrinterCapabilitiesInfo;
import android.print.PrinterId;
import android.print.PrinterInfo;
import android.printservice.PrintService;
import android.printservice.PrintServiceInfo;
import android.provider.DocumentsContract;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.TypedValue;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;

import android.widget.Toast;
import com.android.internal.logging.MetricsLogger;
import com.android.printspooler.R;
import com.android.printspooler.model.MutexFileProvider;
import com.android.printspooler.model.PrintSpoolerProvider;
import com.android.printspooler.model.PrintSpoolerService;
import com.android.printspooler.model.RemotePrintDocument;
import com.android.printspooler.model.RemotePrintDocument.RemotePrintDocumentInfo;
import com.android.printspooler.renderer.IPdfEditor;
import com.android.printspooler.renderer.PdfManipulationService;
import com.android.printspooler.util.ApprovedPrintServices;
import com.android.printspooler.util.MediaSizeUtils;
import com.android.printspooler.util.MediaSizeUtils.MediaSizeComparator;
import com.android.printspooler.util.PageRangeUtils;
import com.android.printspooler.widget.PrintContentView;
import com.android.printspooler.widget.PrintContentView.OptionsStateChangeListener;
import com.android.printspooler.widget.PrintContentView.OptionsStateController;

import libcore.io.IoUtils;
import libcore.io.Streams;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

public class PrintActivity extends Activity implements RemotePrintDocument.UpdateResultCallbacks,
        PrintErrorFragment.OnActionListener, PageAdapter.ContentCallbacks,
        OptionsStateChangeListener, OptionsStateController,
        LoaderManager.LoaderCallbacks<List<PrintServiceInfo>> {
    private static final String LOG_TAG = "PrintActivity";

    private static final boolean DEBUG = false;

    private static final String FRAGMENT_TAG = "FRAGMENT_TAG";

    private static final String HAS_PRINTED_PREF = "has_printed";

    private static final int LOADER_ID_ENABLED_PRINT_SERVICES = 1;
    private static final int LOADER_ID_PRINT_REGISTRY = 2;
    private static final int LOADER_ID_PRINT_REGISTRY_INT = 3;

    private static final int ORIENTATION_PORTRAIT = 0;
    private static final int ORIENTATION_LANDSCAPE = 1;

    private static final int ACTIVITY_REQUEST_CREATE_FILE = 1;
    private static final int ACTIVITY_REQUEST_SELECT_PRINTER = 2;
    private static final int ACTIVITY_REQUEST_POPULATE_ADVANCED_PRINT_OPTIONS = 3;

    private static final int DEST_ADAPTER_MAX_ITEM_COUNT = 9;

    private static final int DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF = Integer.MAX_VALUE;
    private static final int DEST_ADAPTER_ITEM_ID_MORE = Integer.MAX_VALUE - 1;

    private static final int STATE_INITIALIZING = 0;
    private static final int STATE_CONFIGURING = 1;
    private static final int STATE_PRINT_CONFIRMED = 2;
    private static final int STATE_PRINT_CANCELED = 3;
    private static final int STATE_UPDATE_FAILED = 4;
    private static final int STATE_CREATE_FILE_FAILED = 5;
    private static final int STATE_PRINTER_UNAVAILABLE = 6;
    private static final int STATE_UPDATE_SLOW = 7;
    private static final int STATE_PRINT_COMPLETED = 8;

    private static final int UI_STATE_PREVIEW = 0;
    private static final int UI_STATE_ERROR = 1;
    private static final int UI_STATE_PROGRESS = 2;

    private static final int MIN_COPIES = 1;
    private static final String MIN_COPIES_STRING = String.valueOf(MIN_COPIES);

    private boolean mIsOptionsUiBound = false;

    private final PrinterAvailabilityDetector mPrinterAvailabilityDetector =
            new PrinterAvailabilityDetector();

    private final OnFocusChangeListener mSelectAllOnFocusListener = new SelectAllOnFocusListener();

    private PrintSpoolerProvider mSpoolerProvider;

    private PrintPreviewController mPrintPreviewController;

    private PrintJobInfo mPrintJob;
    private RemotePrintDocument mPrintedDocument;
    private PrinterRegistry mPrinterRegistry;

    private EditText mCopiesEditText;

    private TextView mPageRangeTitle;
    private EditText mPageRangeEditText;

    private Spinner mDestinationSpinner;
    private DestinationAdapter mDestinationSpinnerAdapter;
    private boolean mShowDestinationPrompt;

    private Spinner mMediaSizeSpinner;
    private ArrayAdapter<SpinnerItem<MediaSize>> mMediaSizeSpinnerAdapter;

    private Spinner mColorModeSpinner;
    private ArrayAdapter<SpinnerItem<Integer>> mColorModeSpinnerAdapter;

    private Spinner mDuplexModeSpinner;
    private ArrayAdapter<SpinnerItem<Integer>> mDuplexModeSpinnerAdapter;

    private Spinner mOrientationSpinner;
    private ArrayAdapter<SpinnerItem<Integer>> mOrientationSpinnerAdapter;

    private Spinner mRangeOptionsSpinner;

    private PrintContentView mOptionsContent;

    private View mSummaryContainer;
    private TextView mSummaryCopies;
    private TextView mSummaryPaperSize;

    private Button mMoreOptionsButton;

    private ImageView mPrintButton;

    private ProgressMessageController mProgressMessageController;
    private MutexFileProvider mFileProvider;

    private MediaSizeComparator mMediaSizeComparator;

    private PrinterInfo mCurrentPrinter;

    private PageRange[] mSelectedPages;

    private String mCallingPackageName;

    private int mCurrentPageCount;

    private int mState = STATE_INITIALIZING;

    private int mUiState = UI_STATE_PREVIEW;

    /** Observer for changes to the printers */
    private PrintersObserver mPrintersObserver;

    /** Advances options activity name for current printer */
    private ComponentName mAdvancedPrintOptionsActivity;

    /** Whether at least one print services is enabled or not */
    private boolean mArePrintServicesEnabled;

    /** Is doFinish() already in progress */
    private boolean mIsFinishing;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setTitle(R.string.print_dialog);

        Bundle extras = getIntent().getExtras();

        mPrintJob = extras.getParcelable(PrintManager.EXTRA_PRINT_JOB);
        if (mPrintJob == null) {
            throw new IllegalArgumentException(PrintManager.EXTRA_PRINT_JOB
                    + " cannot be null");
        }
        if (mPrintJob.getAttributes() == null) {
            mPrintJob.setAttributes(new PrintAttributes.Builder().build());
        }

        final IBinder adapter = extras.getBinder(PrintManager.EXTRA_PRINT_DOCUMENT_ADAPTER);
        if (adapter == null) {
            throw new IllegalArgumentException(PrintManager.EXTRA_PRINT_DOCUMENT_ADAPTER
                    + " cannot be null");
        }

        mCallingPackageName = extras.getString(DocumentsContract.EXTRA_PACKAGE_NAME);

        // This will take just a few milliseconds, so just wait to
        // bind to the local service before showing the UI.
        mSpoolerProvider = new PrintSpoolerProvider(this,
                new Runnable() {
            @Override
            public void run() {
                if (isFinishing() || isDestroyed()) {
                    // onPause might have not been able to cancel the job, see PrintActivity#onPause
                    // To be sure, cancel the job again. Double canceling does no harm.
                    mSpoolerProvider.getSpooler().setPrintJobState(mPrintJob.getId(),
                            PrintJobInfo.STATE_CANCELED, null);
                } else {
                    onConnectedToPrintSpooler(adapter);
                }
            }
        });

        getLoaderManager().initLoader(LOADER_ID_ENABLED_PRINT_SERVICES, null, this);
    }

    private void onConnectedToPrintSpooler(final IBinder documentAdapter) {
        // Now that we are bound to the print spooler service,
        // create the printer registry and wait for it to get
        // the first batch of results which will be delivered
        // after reading historical data. This should be pretty
        // fast, so just wait before showing the UI.
        mPrinterRegistry = new PrinterRegistry(PrintActivity.this, () -> {
            (new Handler(getMainLooper())).post(() -> onPrinterRegistryReady(documentAdapter));
        }, LOADER_ID_PRINT_REGISTRY, LOADER_ID_PRINT_REGISTRY_INT);
    }

    private void onPrinterRegistryReady(IBinder documentAdapter) {
        // Now that we are bound to the local print spooler service
        // and the printer registry loaded the historical printers
        // we can show the UI without flickering.
        setContentView(R.layout.print_activity);

        try {
            mFileProvider = new MutexFileProvider(
                    PrintSpoolerService.generateFileForPrintJob(
                            PrintActivity.this, mPrintJob.getId()));
        } catch (IOException ioe) {
            // At this point we cannot recover, so just take it down.
            throw new IllegalStateException("Cannot create print job file", ioe);
        }

        mPrintPreviewController = new PrintPreviewController(PrintActivity.this,
                mFileProvider);
        mPrintedDocument = new RemotePrintDocument(PrintActivity.this,
                IPrintDocumentAdapter.Stub.asInterface(documentAdapter),
                mFileProvider, new RemotePrintDocument.RemoteAdapterDeathObserver() {
            @Override
            public void onDied() {
                Log.w(LOG_TAG, "Printing app died unexpectedly");

                // If we are finishing or we are in a state that we do not need any
                // data from the printing app, then no need to finish.
                if (isFinishing() || isDestroyed() ||
                        (isFinalState(mState) && !mPrintedDocument.isUpdating())) {
                    return;
                }
                setState(STATE_PRINT_CANCELED);
                mPrintedDocument.cancel(true);
                doFinish();
            }
        }, PrintActivity.this);
        mProgressMessageController = new ProgressMessageController(
                PrintActivity.this);
        mMediaSizeComparator = new MediaSizeComparator(PrintActivity.this);
        mDestinationSpinnerAdapter = new DestinationAdapter();

        bindUi();
        updateOptionsUi();

        // Now show the updated UI to avoid flicker.
        mOptionsContent.setVisibility(View.VISIBLE);
        mSelectedPages = computeSelectedPages();
        mPrintedDocument.start();

        ensurePreviewUiShown();

        setState(STATE_CONFIGURING);
    }

    @Override
    public void onStart() {
        super.onStart();
        if (mPrinterRegistry != null && mCurrentPrinter != null) {
            mPrinterRegistry.setTrackedPrinter(mCurrentPrinter.getId());
        }
        MetricsLogger.count(this, "print_preview", 1);
    }

    @Override
    public void onPause() {
        PrintSpoolerService spooler = mSpoolerProvider.getSpooler();

        if (mState == STATE_INITIALIZING) {
            if (isFinishing()) {
                if (spooler != null) {
                    spooler.setPrintJobState(mPrintJob.getId(), PrintJobInfo.STATE_CANCELED, null);
                }
            }
            super.onPause();
            return;
        }

        if (isFinishing()) {
            spooler.updatePrintJobUserConfigurableOptionsNoPersistence(mPrintJob);

            switch (mState) {
                case STATE_PRINT_COMPLETED: {
                    if (mCurrentPrinter == mDestinationSpinnerAdapter.getPdfPrinter()) {
                        spooler.setPrintJobState(mPrintJob.getId(), PrintJobInfo.STATE_COMPLETED,
                                null);
                    } else {
                        spooler.setPrintJobState(mPrintJob.getId(), PrintJobInfo.STATE_QUEUED,
                                null);
                    }
                } break;

                case STATE_CREATE_FILE_FAILED: {
                    spooler.setPrintJobState(mPrintJob.getId(), PrintJobInfo.STATE_FAILED,
                            getString(R.string.print_write_error_message));
                } break;

                default: {
                    spooler.setPrintJobState(mPrintJob.getId(), PrintJobInfo.STATE_CANCELED, null);
                } break;
            }
        }

        super.onPause();
    }

    @Override
    protected void onStop() {
        mPrinterAvailabilityDetector.cancel();

        if (mPrinterRegistry != null) {
            mPrinterRegistry.setTrackedPrinter(null);
        }

        super.onStop();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            event.startTracking();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (mState == STATE_INITIALIZING) {
            doFinish();
            return true;
        }

        if (mState == STATE_PRINT_CANCELED || mState == STATE_PRINT_CONFIRMED
                || mState == STATE_PRINT_COMPLETED) {
            return true;
        }

        if (keyCode == KeyEvent.KEYCODE_BACK
                && event.isTracking() && !event.isCanceled()) {
            if (mPrintPreviewController != null && mPrintPreviewController.isOptionsOpened()
                    && !hasErrors()) {
                mPrintPreviewController.closeOptions();
            } else {
                cancelPrint();
            }
            return true;
        }
        return super.onKeyUp(keyCode, event);
    }

    @Override
    public void onRequestContentUpdate() {
        if (canUpdateDocument()) {
            updateDocument(false);
        }
    }

    @Override
    public void onMalformedPdfFile() {
        onPrintDocumentError("Cannot print a malformed PDF file");
    }

    @Override
    public void onSecurePdfFile() {
        onPrintDocumentError("Cannot print a password protected PDF file");
    }

    private void onPrintDocumentError(String message) {
        setState(mProgressMessageController.cancel());
        ensureErrorUiShown(null, PrintErrorFragment.ACTION_RETRY);

        setState(STATE_UPDATE_FAILED);

        updateOptionsUi();

        mPrintedDocument.kill(message);
    }

    @Override
    public void onActionPerformed() {
        if (mState == STATE_UPDATE_FAILED
                && canUpdateDocument() && updateDocument(true)) {
            ensurePreviewUiShown();
            setState(STATE_CONFIGURING);
            updateOptionsUi();
        }
    }

    @Override
    public void onUpdateCanceled() {
        if (DEBUG) {
            Log.i(LOG_TAG, "onUpdateCanceled()");
        }

        setState(mProgressMessageController.cancel());
        ensurePreviewUiShown();

        switch (mState) {
            case STATE_PRINT_CONFIRMED: {
                requestCreatePdfFileOrFinish();
            } break;

            case STATE_CREATE_FILE_FAILED:
            case STATE_PRINT_COMPLETED:
            case STATE_PRINT_CANCELED: {
                doFinish();
            } break;
        }
    }

    @Override
    public void onUpdateCompleted(RemotePrintDocumentInfo document) {
        if (DEBUG) {
            Log.i(LOG_TAG, "onUpdateCompleted()");
        }

        setState(mProgressMessageController.cancel());
        ensurePreviewUiShown();

        // Update the print job with the info for the written document. The page
        // count we get from the remote document is the pages in the document from
        // the app perspective but the print job should contain the page count from
        // print service perspective which is the pages in the written PDF not the
        // pages in the printed document.
        PrintDocumentInfo info = document.info;
        if (info != null) {
            final int pageCount = PageRangeUtils.getNormalizedPageCount(document.writtenPages,
                    getAdjustedPageCount(info));
            PrintDocumentInfo adjustedInfo = new PrintDocumentInfo.Builder(info.getName())
                    .setContentType(info.getContentType())
                    .setPageCount(pageCount)
                    .build();

            File file = mFileProvider.acquireFile(null);
            try {
                adjustedInfo.setDataSize(file.length());
            } finally {
                mFileProvider.releaseFile();
            }

            mPrintJob.setDocumentInfo(adjustedInfo);
            mPrintJob.setPages(document.printedPages);
        }

        switch (mState) {
            case STATE_PRINT_CONFIRMED: {
                requestCreatePdfFileOrFinish();
            } break;

            case STATE_CREATE_FILE_FAILED:
            case STATE_PRINT_COMPLETED:
            case STATE_PRINT_CANCELED: {
                updateOptionsUi();

                doFinish();
            } break;

            default: {
                updatePrintPreviewController(document.changed);

                setState(STATE_CONFIGURING);
                updateOptionsUi();
            } break;
        }
    }

    @Override
    public void onUpdateFailed(CharSequence error) {
        if (DEBUG) {
            Log.i(LOG_TAG, "onUpdateFailed()");
        }

        setState(mProgressMessageController.cancel());
        ensureErrorUiShown(error, PrintErrorFragment.ACTION_RETRY);

        if (mState == STATE_CREATE_FILE_FAILED
                || mState == STATE_PRINT_COMPLETED
                || mState == STATE_PRINT_CANCELED) {
            doFinish();
        }

        setState(STATE_UPDATE_FAILED);

        updateOptionsUi();
    }

    @Override
    public void onOptionsOpened() {
        updateSelectedPagesFromPreview();
    }

    @Override
    public void onOptionsClosed() {
        // Make sure the IME is not on the way of preview as
        // the user may have used it to type copies or range.
        InputMethodManager imm = getSystemService(InputMethodManager.class);
        imm.hideSoftInputFromWindow(mDestinationSpinner.getWindowToken(), 0);
    }

    private void updatePrintPreviewController(boolean contentUpdated) {
        // If we have not heard from the application, do nothing.
        RemotePrintDocumentInfo documentInfo = mPrintedDocument.getDocumentInfo();
        if (!documentInfo.laidout) {
            return;
        }

        // Update the preview controller.
        mPrintPreviewController.onContentUpdated(contentUpdated,
                getAdjustedPageCount(documentInfo.info),
                mPrintedDocument.getDocumentInfo().writtenPages,
                mSelectedPages, mPrintJob.getAttributes().getMediaSize(),
                mPrintJob.getAttributes().getMinMargins());
    }


    @Override
    public boolean canOpenOptions() {
        return true;
    }

    @Override
    public boolean canCloseOptions() {
        return !hasErrors();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        mMediaSizeComparator.onConfigurationChanged(newConfig);

        if (mPrintPreviewController != null) {
            mPrintPreviewController.onOrientationChanged();
        }
    }

    @Override
    protected void onDestroy() {
        if (mPrintedDocument != null) {
            mPrintedDocument.cancel(true);
        }

        doFinish();

        super.onDestroy();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case ACTIVITY_REQUEST_CREATE_FILE: {
                onStartCreateDocumentActivityResult(resultCode, data);
            } break;

            case ACTIVITY_REQUEST_SELECT_PRINTER: {
                onSelectPrinterActivityResult(resultCode, data);
            } break;

            case ACTIVITY_REQUEST_POPULATE_ADVANCED_PRINT_OPTIONS: {
                onAdvancedPrintOptionsActivityResult(resultCode, data);
            } break;
        }
    }

    private void startCreateDocumentActivity() {
        if (!isResumed()) {
            return;
        }
        PrintDocumentInfo info = mPrintedDocument.getDocumentInfo().info;
        if (info == null) {
            return;
        }
        Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
        intent.setType("application/pdf");
        intent.putExtra(Intent.EXTRA_TITLE, info.getName());
        intent.putExtra(DocumentsContract.EXTRA_PACKAGE_NAME, mCallingPackageName);

        try {
            startActivityForResult(intent, ACTIVITY_REQUEST_CREATE_FILE);
        } catch (Exception e) {
            Log.e(LOG_TAG, "Could not create file", e);
            Toast.makeText(this, getString(R.string.could_not_create_file),
                    Toast.LENGTH_SHORT).show();
            onStartCreateDocumentActivityResult(RESULT_CANCELED, null);
        }
    }

    private void onStartCreateDocumentActivityResult(int resultCode, Intent data) {
        if (resultCode == RESULT_OK && data != null) {
            updateOptionsUi();
            final Uri uri = data.getData();
            // Calling finish here does not invoke lifecycle callbacks but we
            // update the print job in onPause if finishing, hence post a message.
            mDestinationSpinner.post(new Runnable() {
                @Override
                public void run() {
                    transformDocumentAndFinish(uri);
                }
            });
        } else if (resultCode == RESULT_CANCELED) {
            if (DEBUG) {
                Log.i(LOG_TAG, "[state]" + STATE_CONFIGURING);
            }

            mState = STATE_CONFIGURING;

            // The previous update might have been canceled
            updateDocument(false);

            updateOptionsUi();
        } else {
            setState(STATE_CREATE_FILE_FAILED);
            updateOptionsUi();
            // Calling finish here does not invoke lifecycle callbacks but we
            // update the print job in onPause if finishing, hence post a message.
            mDestinationSpinner.post(new Runnable() {
                @Override
                public void run() {
                    doFinish();
                }
            });
        }
    }

    private void startSelectPrinterActivity() {
        Intent intent = new Intent(this, SelectPrinterActivity.class);
        startActivityForResult(intent, ACTIVITY_REQUEST_SELECT_PRINTER);
    }

    private void onSelectPrinterActivityResult(int resultCode, Intent data) {
        if (resultCode == RESULT_OK && data != null) {
            PrinterInfo printerInfo = data.getParcelableExtra(
                    SelectPrinterActivity.INTENT_EXTRA_PRINTER);
            if (printerInfo != null) {
                mCurrentPrinter = printerInfo;
                mPrintJob.setPrinterId(printerInfo.getId());
                mPrintJob.setPrinterName(printerInfo.getName());

                mDestinationSpinnerAdapter.ensurePrinterInVisibleAdapterPosition(printerInfo);
            }
        }

        if (mCurrentPrinter != null) {
            // Trigger PrintersObserver.onChanged() to adjust selection back to current printer
            mDestinationSpinnerAdapter.notifyDataSetChanged();
        }
    }

    private void startAdvancedPrintOptionsActivity(PrinterInfo printer) {
        if (mAdvancedPrintOptionsActivity == null) {
            return;
        }

        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.setComponent(mAdvancedPrintOptionsActivity);

        List<ResolveInfo> resolvedActivities = getPackageManager()
                .queryIntentActivities(intent, 0);
        if (resolvedActivities.isEmpty()) {
            return;
        }

        // The activity is a component name, therefore it is one or none.
        if (resolvedActivities.get(0).activityInfo.exported) {
            PrintJobInfo.Builder printJobBuilder = new PrintJobInfo.Builder(mPrintJob);
            printJobBuilder.setPages(mSelectedPages);

            intent.putExtra(PrintService.EXTRA_PRINT_JOB_INFO, printJobBuilder.build());
            intent.putExtra(PrintService.EXTRA_PRINTER_INFO, printer);
            intent.putExtra(PrintService.EXTRA_PRINT_DOCUMENT_INFO,
                    mPrintedDocument.getDocumentInfo().info);

            // This is external activity and may not be there.
            try {
                startActivityForResult(intent, ACTIVITY_REQUEST_POPULATE_ADVANCED_PRINT_OPTIONS);
            } catch (ActivityNotFoundException anfe) {
                Log.e(LOG_TAG, "Error starting activity for intent: " + intent, anfe);
            }
        }
    }

    private void onAdvancedPrintOptionsActivityResult(int resultCode, Intent data) {
        if (resultCode != RESULT_OK || data == null) {
            return;
        }

        PrintJobInfo printJobInfo = data.getParcelableExtra(PrintService.EXTRA_PRINT_JOB_INFO);

        if (printJobInfo == null) {
            return;
        }

        // Take the advanced options without interpretation.
        mPrintJob.setAdvancedOptions(printJobInfo.getAdvancedOptions());

        if (printJobInfo.getCopies() < 1) {
            Log.w(LOG_TAG, "Cannot apply return value from advanced options activity. Copies " +
                    "must be 1 or more. Actual value is: " + printJobInfo.getCopies() + ". " +
                    "Ignoring.");
        } else {
            mCopiesEditText.setText(String.valueOf(printJobInfo.getCopies()));
            mPrintJob.setCopies(printJobInfo.getCopies());
        }

        PrintAttributes currAttributes = mPrintJob.getAttributes();
        PrintAttributes newAttributes = printJobInfo.getAttributes();

        if (newAttributes != null) {
            // Take the media size only if the current printer supports is.
            MediaSize oldMediaSize = currAttributes.getMediaSize();
            MediaSize newMediaSize = newAttributes.getMediaSize();
            if (newMediaSize != null && !oldMediaSize.equals(newMediaSize)) {
                final int mediaSizeCount = mMediaSizeSpinnerAdapter.getCount();
                MediaSize newMediaSizePortrait = newAttributes.getMediaSize().asPortrait();
                for (int i = 0; i < mediaSizeCount; i++) {
                    MediaSize supportedSizePortrait = mMediaSizeSpinnerAdapter.getItem(i)
                            .value.asPortrait();
                    if (supportedSizePortrait.equals(newMediaSizePortrait)) {
                        currAttributes.setMediaSize(newMediaSize);
                        mMediaSizeSpinner.setSelection(i);
                        if (currAttributes.getMediaSize().isPortrait()) {
                            if (mOrientationSpinner.getSelectedItemPosition() != 0) {
                                mOrientationSpinner.setSelection(0);
                            }
                        } else {
                            if (mOrientationSpinner.getSelectedItemPosition() != 1) {
                                mOrientationSpinner.setSelection(1);
                            }
                        }
                        break;
                    }
                }
            }

            // Take the resolution only if the current printer supports is.
            Resolution oldResolution = currAttributes.getResolution();
            Resolution newResolution = newAttributes.getResolution();
            if (!oldResolution.equals(newResolution)) {
                PrinterCapabilitiesInfo capabilities = mCurrentPrinter.getCapabilities();
                if (capabilities != null) {
                    List<Resolution> resolutions = capabilities.getResolutions();
                    final int resolutionCount = resolutions.size();
                    for (int i = 0; i < resolutionCount; i++) {
                        Resolution resolution = resolutions.get(i);
                        if (resolution.equals(newResolution)) {
                            currAttributes.setResolution(resolution);
                            break;
                        }
                    }
                }
            }

            // Take the color mode only if the current printer supports it.
            final int currColorMode = currAttributes.getColorMode();
            final int newColorMode = newAttributes.getColorMode();
            if (currColorMode != newColorMode) {
                final int colorModeCount = mColorModeSpinner.getCount();
                for (int i = 0; i < colorModeCount; i++) {
                    final int supportedColorMode = mColorModeSpinnerAdapter.getItem(i).value;
                    if (supportedColorMode == newColorMode) {
                        currAttributes.setColorMode(newColorMode);
                        mColorModeSpinner.setSelection(i);
                        break;
                    }
                }
            }

            // Take the duplex mode only if the current printer supports it.
            final int currDuplexMode = currAttributes.getDuplexMode();
            final int newDuplexMode = newAttributes.getDuplexMode();
            if (currDuplexMode != newDuplexMode) {
                final int duplexModeCount = mDuplexModeSpinner.getCount();
                for (int i = 0; i < duplexModeCount; i++) {
                    final int supportedDuplexMode = mDuplexModeSpinnerAdapter.getItem(i).value;
                    if (supportedDuplexMode == newDuplexMode) {
                        currAttributes.setDuplexMode(newDuplexMode);
                        mDuplexModeSpinner.setSelection(i);
                        break;
                    }
                }
            }
        }

        // Handle selected page changes making sure they are in the doc.
        PrintDocumentInfo info = mPrintedDocument.getDocumentInfo().info;
        final int pageCount = (info != null) ? getAdjustedPageCount(info) : 0;
        PageRange[] pageRanges = printJobInfo.getPages();
        if (pageRanges != null && pageCount > 0) {
            pageRanges = PageRangeUtils.normalize(pageRanges);

            List<PageRange> validatedList = new ArrayList<>();
            final int rangeCount = pageRanges.length;
            for (int i = 0; i < rangeCount; i++) {
                PageRange pageRange = pageRanges[i];
                if (pageRange.getEnd() >= pageCount) {
                    final int rangeStart = pageRange.getStart();
                    final int rangeEnd = pageCount - 1;
                    if (rangeStart <= rangeEnd) {
                        pageRange = new PageRange(rangeStart, rangeEnd);
                        validatedList.add(pageRange);
                    }
                    break;
                }
                validatedList.add(pageRange);
            }

            if (!validatedList.isEmpty()) {
                PageRange[] validatedArray = new PageRange[validatedList.size()];
                validatedList.toArray(validatedArray);
                updateSelectedPages(validatedArray, pageCount);
            }
        }

        // Update the content if needed.
        if (canUpdateDocument()) {
            updateDocument(false);
        }
    }

    private void setState(int state) {
        if (isFinalState(mState)) {
            if (isFinalState(state)) {
                if (DEBUG) {
                    Log.i(LOG_TAG, "[state]" + state);
                }
                mState = state;
            }
        } else {
            if (DEBUG) {
                Log.i(LOG_TAG, "[state]" + state);
            }
            mState = state;
        }
    }

    private static boolean isFinalState(int state) {
        return state == STATE_PRINT_CANCELED
                || state == STATE_PRINT_COMPLETED
                || state == STATE_CREATE_FILE_FAILED;
    }

    private void updateSelectedPagesFromPreview() {
        PageRange[] selectedPages = mPrintPreviewController.getSelectedPages();
        if (!Arrays.equals(mSelectedPages, selectedPages)) {
            updateSelectedPages(selectedPages,
                    getAdjustedPageCount(mPrintedDocument.getDocumentInfo().info));
        }
    }

    private void updateSelectedPages(PageRange[] selectedPages, int pageInDocumentCount) {
        if (selectedPages == null || selectedPages.length <= 0) {
            return;
        }

        selectedPages = PageRangeUtils.normalize(selectedPages);

        // Handle the case where all pages are specified explicitly
        // instead of the *all pages* constant.
        if (PageRangeUtils.isAllPages(selectedPages, pageInDocumentCount)) {
            selectedPages = new PageRange[] {PageRange.ALL_PAGES};
        }

        if (Arrays.equals(mSelectedPages, selectedPages)) {
            return;
        }

        mSelectedPages = selectedPages;
        mPrintJob.setPages(selectedPages);

        if (Arrays.equals(selectedPages, PageRange.ALL_PAGES_ARRAY)) {
            if (mRangeOptionsSpinner.getSelectedItemPosition() != 0) {
                mRangeOptionsSpinner.setSelection(0);
                mPageRangeEditText.setText("");
            }
        } else if (selectedPages[0].getStart() >= 0
                && selectedPages[selectedPages.length - 1].getEnd() < pageInDocumentCount) {
            if (mRangeOptionsSpinner.getSelectedItemPosition() != 1) {
                mRangeOptionsSpinner.setSelection(1);
            }

            StringBuilder builder = new StringBuilder();
            final int pageRangeCount = selectedPages.length;
            for (int i = 0; i < pageRangeCount; i++) {
                if (builder.length() > 0) {
                    builder.append(',');
                }

                final int shownStartPage;
                final int shownEndPage;
                PageRange pageRange = selectedPages[i];
                if (pageRange.equals(PageRange.ALL_PAGES)) {
                    shownStartPage = 1;
                    shownEndPage = pageInDocumentCount;
                } else {
                    shownStartPage = pageRange.getStart() + 1;
                    shownEndPage = pageRange.getEnd() + 1;
                }

                builder.append(shownStartPage);

                if (shownStartPage != shownEndPage) {
                    builder.append('-');
                    builder.append(shownEndPage);
                }
            }

            mPageRangeEditText.setText(builder.toString());
        }
    }

    private void ensureProgressUiShown() {
        if (isFinishing() || isDestroyed()) {
            return;
        }
        if (mUiState != UI_STATE_PROGRESS) {
            mUiState = UI_STATE_PROGRESS;
            mPrintPreviewController.setUiShown(false);
            Fragment fragment = PrintProgressFragment.newInstance();
            showFragment(fragment);
        }
    }

    private void ensurePreviewUiShown() {
        if (isFinishing() || isDestroyed()) {
            return;
        }
        if (mUiState != UI_STATE_PREVIEW) {
            mUiState = UI_STATE_PREVIEW;
            mPrintPreviewController.setUiShown(true);
            showFragment(null);
        }
    }

    private void ensureErrorUiShown(CharSequence message, int action) {
        if (isFinishing() || isDestroyed()) {
            return;
        }
        if (mUiState != UI_STATE_ERROR) {
            mUiState = UI_STATE_ERROR;
            mPrintPreviewController.setUiShown(false);
            Fragment fragment = PrintErrorFragment.newInstance(message, action);
            showFragment(fragment);
        }
    }

    private void showFragment(Fragment newFragment) {
        FragmentTransaction transaction = getFragmentManager().beginTransaction();
        Fragment oldFragment = getFragmentManager().findFragmentByTag(FRAGMENT_TAG);
        if (oldFragment != null) {
            transaction.remove(oldFragment);
        }
        if (newFragment != null) {
            transaction.add(R.id.embedded_content_container, newFragment, FRAGMENT_TAG);
        }
        transaction.commitAllowingStateLoss();
        getFragmentManager().executePendingTransactions();
    }

    private void requestCreatePdfFileOrFinish() {
        mPrintedDocument.cancel(false);

        if (mCurrentPrinter == mDestinationSpinnerAdapter.getPdfPrinter()) {
            startCreateDocumentActivity();
        } else {
            transformDocumentAndFinish(null);
        }
    }

    /**
     * Clear the selected page range and update the preview if needed.
     */
    private void clearPageRanges() {
        mRangeOptionsSpinner.setSelection(0);
        mPageRangeEditText.setError(null);
        mPageRangeEditText.setText("");
        mSelectedPages = PageRange.ALL_PAGES_ARRAY;

        if (!Arrays.equals(mSelectedPages, mPrintPreviewController.getSelectedPages())) {
            updatePrintPreviewController(false);
        }
    }

    private void updatePrintAttributesFromCapabilities(PrinterCapabilitiesInfo capabilities) {
        boolean clearRanges = false;
        PrintAttributes defaults = capabilities.getDefaults();

        // Sort the media sizes based on the current locale.
        List<MediaSize> sortedMediaSizes = new ArrayList<>(capabilities.getMediaSizes());
        Collections.sort(sortedMediaSizes, mMediaSizeComparator);

        PrintAttributes attributes = mPrintJob.getAttributes();

        // Media size.
        MediaSize currMediaSize = attributes.getMediaSize();
        if (currMediaSize == null) {
            clearRanges = true;
            attributes.setMediaSize(defaults.getMediaSize());
        } else {
            MediaSize newMediaSize = null;
            boolean isPortrait = currMediaSize.isPortrait();

            // Try to find the current media size in the capabilities as
            // it may be in a different orientation.
            MediaSize currMediaSizePortrait = currMediaSize.asPortrait();
            final int mediaSizeCount = sortedMediaSizes.size();
            for (int i = 0; i < mediaSizeCount; i++) {
                MediaSize mediaSize = sortedMediaSizes.get(i);
                if (currMediaSizePortrait.equals(mediaSize.asPortrait())) {
                    newMediaSize = mediaSize;
                    break;
                }
            }
            // If we did not find the current media size fall back to default.
            if (newMediaSize == null) {
                clearRanges = true;
                newMediaSize = defaults.getMediaSize();
            }

            if (newMediaSize != null) {
                if (isPortrait) {
                    attributes.setMediaSize(newMediaSize.asPortrait());
                } else {
                    attributes.setMediaSize(newMediaSize.asLandscape());
                }
            }
        }

        // Color mode.
        final int colorMode = attributes.getColorMode();
        if ((capabilities.getColorModes() & colorMode) == 0) {
            attributes.setColorMode(defaults.getColorMode());
        }

        // Duplex mode.
        final int duplexMode = attributes.getDuplexMode();
        if ((capabilities.getDuplexModes() & duplexMode) == 0) {
            attributes.setDuplexMode(defaults.getDuplexMode());
        }

        // Resolution
        Resolution resolution = attributes.getResolution();
        if (resolution == null || !capabilities.getResolutions().contains(resolution)) {
            attributes.setResolution(defaults.getResolution());
        }

        // Margins.
        if (!Objects.equals(attributes.getMinMargins(), defaults.getMinMargins())) {
            clearRanges = true;
        }
        attributes.setMinMargins(defaults.getMinMargins());

        if (clearRanges) {
            clearPageRanges();
        }
    }

    private boolean updateDocument(boolean clearLastError) {
        if (!clearLastError && mPrintedDocument.hasUpdateError()) {
            return false;
        }

        if (clearLastError && mPrintedDocument.hasUpdateError()) {
            mPrintedDocument.clearUpdateError();
        }

        final boolean preview = mState != STATE_PRINT_CONFIRMED;
        final PageRange[] pages;
        if (preview) {
            pages = mPrintPreviewController.getRequestedPages();
        } else {
            pages = mPrintPreviewController.getSelectedPages();
        }

        final boolean willUpdate = mPrintedDocument.update(mPrintJob.getAttributes(),
                pages, preview);

        if (willUpdate && !mPrintedDocument.hasLaidOutPages()) {
            // When the update is done we update the print preview.
            mProgressMessageController.post();
            return true;
        } else if (!willUpdate) {
            // Update preview.
            updatePrintPreviewController(false);
        }

        return false;
    }

    private void addCurrentPrinterToHistory() {
        if (mCurrentPrinter != null) {
            PrinterId fakePdfPrinterId = mDestinationSpinnerAdapter.getPdfPrinter().getId();
            if (!mCurrentPrinter.getId().equals(fakePdfPrinterId)) {
                mPrinterRegistry.addHistoricalPrinter(mCurrentPrinter);
            }
        }
    }

    private void cancelPrint() {
        setState(STATE_PRINT_CANCELED);
        updateOptionsUi();
        mPrintedDocument.cancel(true);
        doFinish();
    }

    /**
     * Update the selected pages from the text field.
     */
    private void updateSelectedPagesFromTextField() {
        PageRange[] selectedPages = computeSelectedPages();
        if (!Arrays.equals(mSelectedPages, selectedPages)) {
            mSelectedPages = selectedPages;
            // Update preview.
            updatePrintPreviewController(false);
        }
    }

    private void confirmPrint() {
        setState(STATE_PRINT_CONFIRMED);

        MetricsLogger.count(this, "print_confirmed", 1);

        updateOptionsUi();
        addCurrentPrinterToHistory();
        setUserPrinted();

        // updateSelectedPagesFromTextField migth update the preview, hence apply the preview first
        updateSelectedPagesFromPreview();
        updateSelectedPagesFromTextField();

        mPrintPreviewController.closeOptions();

        if (canUpdateDocument()) {
            updateDocument(false);
        }

        if (!mPrintedDocument.isUpdating()) {
            requestCreatePdfFileOrFinish();
        }
    }

    private void bindUi() {
        // Summary
        mSummaryContainer = findViewById(R.id.summary_content);
        mSummaryCopies = (TextView) findViewById(R.id.copies_count_summary);
        mSummaryPaperSize = (TextView) findViewById(R.id.paper_size_summary);

        // Options container
        mOptionsContent = (PrintContentView) findViewById(R.id.options_content);
        mOptionsContent.setOptionsStateChangeListener(this);
        mOptionsContent.setOpenOptionsController(this);

        OnItemSelectedListener itemSelectedListener = new MyOnItemSelectedListener();
        OnClickListener clickListener = new MyClickListener();

        // Copies
        mCopiesEditText = (EditText) findViewById(R.id.copies_edittext);
        mCopiesEditText.setOnFocusChangeListener(mSelectAllOnFocusListener);
        mCopiesEditText.setText(MIN_COPIES_STRING);
        mCopiesEditText.setSelection(mCopiesEditText.getText().length());
        mCopiesEditText.addTextChangedListener(new EditTextWatcher());

        // Destination.
        mPrintersObserver = new PrintersObserver();
        mDestinationSpinnerAdapter.registerDataSetObserver(mPrintersObserver);
        mDestinationSpinner = (Spinner) findViewById(R.id.destination_spinner);
        mDestinationSpinner.setAdapter(mDestinationSpinnerAdapter);
        mDestinationSpinner.setOnItemSelectedListener(itemSelectedListener);

        // Media size.
        mMediaSizeSpinnerAdapter = new ArrayAdapter<>(
                this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
        mMediaSizeSpinner = (Spinner) findViewById(R.id.paper_size_spinner);
        mMediaSizeSpinner.setAdapter(mMediaSizeSpinnerAdapter);
        mMediaSizeSpinner.setOnItemSelectedListener(itemSelectedListener);

        // Color mode.
        mColorModeSpinnerAdapter = new ArrayAdapter<>(
                this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
        mColorModeSpinner = (Spinner) findViewById(R.id.color_spinner);
        mColorModeSpinner.setAdapter(mColorModeSpinnerAdapter);
        mColorModeSpinner.setOnItemSelectedListener(itemSelectedListener);

        // Duplex mode.
        mDuplexModeSpinnerAdapter = new ArrayAdapter<>(
                this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
        mDuplexModeSpinner = (Spinner) findViewById(R.id.duplex_spinner);
        mDuplexModeSpinner.setAdapter(mDuplexModeSpinnerAdapter);
        mDuplexModeSpinner.setOnItemSelectedListener(itemSelectedListener);

        // Orientation
        mOrientationSpinnerAdapter = new ArrayAdapter<>(
                this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
        String[] orientationLabels = getResources().getStringArray(
                R.array.orientation_labels);
        mOrientationSpinnerAdapter.add(new SpinnerItem<>(
                ORIENTATION_PORTRAIT, orientationLabels[0]));
        mOrientationSpinnerAdapter.add(new SpinnerItem<>(
                ORIENTATION_LANDSCAPE, orientationLabels[1]));
        mOrientationSpinner = (Spinner) findViewById(R.id.orientation_spinner);
        mOrientationSpinner.setAdapter(mOrientationSpinnerAdapter);
        mOrientationSpinner.setOnItemSelectedListener(itemSelectedListener);

        // Range options
        ArrayAdapter<SpinnerItem<Integer>> rangeOptionsSpinnerAdapter = new ArrayAdapter<>(
                this, android.R.layout.simple_spinner_dropdown_item, android.R.id.text1);
        mRangeOptionsSpinner = (Spinner) findViewById(R.id.range_options_spinner);
        mRangeOptionsSpinner.setAdapter(rangeOptionsSpinnerAdapter);
        mRangeOptionsSpinner.setOnItemSelectedListener(itemSelectedListener);
        updatePageRangeOptions(PrintDocumentInfo.PAGE_COUNT_UNKNOWN);

        // Page range
        mPageRangeTitle = (TextView) findViewById(R.id.page_range_title);
        mPageRangeEditText = (EditText) findViewById(R.id.page_range_edittext);
        mPageRangeEditText.setVisibility(View.INVISIBLE);
        mPageRangeTitle.setVisibility(View.INVISIBLE);
        mPageRangeEditText.setOnFocusChangeListener(mSelectAllOnFocusListener);
        mPageRangeEditText.addTextChangedListener(new RangeTextWatcher());

        // Advanced options button.
        mMoreOptionsButton = (Button) findViewById(R.id.more_options_button);
        mMoreOptionsButton.setOnClickListener(clickListener);

        // Print button
        mPrintButton = (ImageView) findViewById(R.id.print_button);
        mPrintButton.setOnClickListener(clickListener);

        // The UI is now initialized
        mIsOptionsUiBound = true;

        // Special prompt instead of destination spinner for the first time the user printed
        if (!hasUserEverPrinted()) {
            mShowDestinationPrompt = true;

            mSummaryCopies.setEnabled(false);
            mSummaryPaperSize.setEnabled(false);

            mDestinationSpinner.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    mShowDestinationPrompt = false;
                    mSummaryCopies.setEnabled(true);
                    mSummaryPaperSize.setEnabled(true);
                    updateOptionsUi();

                    mDestinationSpinner.setOnTouchListener(null);
                    mDestinationSpinnerAdapter.notifyDataSetChanged();

                    return false;
                }
            });
        }
    }

    @Override
    public Loader<List<PrintServiceInfo>> onCreateLoader(int id, Bundle args) {
        return new PrintServicesLoader((PrintManager) getSystemService(Context.PRINT_SERVICE), this,
                PrintManager.ENABLED_SERVICES);
    }

    @Override
    public void onLoadFinished(Loader<List<PrintServiceInfo>> loader,
            List<PrintServiceInfo> services) {
        ComponentName newAdvancedPrintOptionsActivity = null;
        if (mCurrentPrinter != null && services != null) {
            final int numServices = services.size();
            for (int i = 0; i < numServices; i++) {
                PrintServiceInfo service = services.get(i);

                if (service.getComponentName().equals(mCurrentPrinter.getId().getServiceName())) {
                    String advancedOptionsActivityName = service.getAdvancedOptionsActivityName();

                    if (!TextUtils.isEmpty(advancedOptionsActivityName)) {
                        newAdvancedPrintOptionsActivity = new ComponentName(
                                service.getComponentName().getPackageName(),
                                advancedOptionsActivityName);

                        break;
                    }
                }
            }
        }

        if (!Objects.equals(newAdvancedPrintOptionsActivity, mAdvancedPrintOptionsActivity)) {
            mAdvancedPrintOptionsActivity = newAdvancedPrintOptionsActivity;
            updateOptionsUi();
        }

        boolean newArePrintServicesEnabled = services != null && !services.isEmpty();
        if (mArePrintServicesEnabled != newArePrintServicesEnabled) {
            mArePrintServicesEnabled = newArePrintServicesEnabled;

            // Reload mDestinationSpinnerAdapter as mArePrintServicesEnabled changed and the adapter
            // reads that in DestinationAdapter#getMoreItemTitle
            if (mDestinationSpinnerAdapter != null) {
                mDestinationSpinnerAdapter.notifyDataSetChanged();
            }
        }
    }

    @Override
    public void onLoaderReset(Loader<List<PrintServiceInfo>> loader) {
        if (!(isFinishing() || isDestroyed())) {
            onLoadFinished(loader, null);
        }
    }

    /**
     * A dialog that asks the user to approve a {@link PrintService}. This dialog is automatically
     * dismissed if the same {@link PrintService} gets approved by another
     * {@link PrintServiceApprovalDialog}.
     */
    private static final class PrintServiceApprovalDialog extends DialogFragment
            implements OnSharedPreferenceChangeListener {
        private static final String PRINTSERVICE_KEY = "PRINTSERVICE";
        private ApprovedPrintServices mApprovedServices;

        /**
         * Create a new {@link PrintServiceApprovalDialog} that ask the user to approve a
         * {@link PrintService}.
         *
         * @param printService The {@link ComponentName} of the service to approve
         * @return A new {@link PrintServiceApprovalDialog} that might approve the service
         */
        static PrintServiceApprovalDialog newInstance(ComponentName printService) {
            PrintServiceApprovalDialog dialog = new PrintServiceApprovalDialog();

            Bundle args = new Bundle();
            args.putParcelable(PRINTSERVICE_KEY, printService);
            dialog.setArguments(args);

            return dialog;
        }

        @Override
        public void onStop() {
            super.onStop();

            mApprovedServices.unregisterChangeListener(this);
        }

        @Override
        public void onStart() {
            super.onStart();

            ComponentName printService = getArguments().getParcelable(PRINTSERVICE_KEY);
            synchronized (ApprovedPrintServices.sLock) {
                if (mApprovedServices.isApprovedService(printService)) {
                    dismiss();
                } else {
                    mApprovedServices.registerChangeListenerLocked(this);
                }
            }
        }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            super.onCreateDialog(savedInstanceState);

            mApprovedServices = new ApprovedPrintServices(getActivity());

            PackageManager packageManager = getActivity().getPackageManager();
            CharSequence serviceLabel;
            try {
                ComponentName printService = getArguments().getParcelable(PRINTSERVICE_KEY);

                serviceLabel = packageManager.getApplicationInfo(printService.getPackageName(), 0)
                        .loadLabel(packageManager);
            } catch (NameNotFoundException e) {
                serviceLabel = null;
            }

            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
            builder.setTitle(getString(R.string.print_service_security_warning_title,
                    serviceLabel))
                    .setMessage(getString(R.string.print_service_security_warning_summary,
                            serviceLabel))
                    .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int id) {
                            ComponentName printService =
                                    getArguments().getParcelable(PRINTSERVICE_KEY);
                            // Prevent onSharedPreferenceChanged from getting triggered
                            mApprovedServices
                                    .unregisterChangeListener(PrintServiceApprovalDialog.this);

                            mApprovedServices.addApprovedService(printService);
                            ((PrintActivity) getActivity()).confirmPrint();
                        }
                    })
                    .setNegativeButton(android.R.string.cancel, null);

            return builder.create();
        }

        @Override
        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
            ComponentName printService = getArguments().getParcelable(PRINTSERVICE_KEY);

            synchronized (ApprovedPrintServices.sLock) {
                if (mApprovedServices.isApprovedService(printService)) {
                    dismiss();
                }
            }
        }
    }

    private final class MyClickListener implements OnClickListener {
        @Override
        public void onClick(View view) {
            if (view == mPrintButton) {
                if (mCurrentPrinter != null) {
                    if (mDestinationSpinnerAdapter.getPdfPrinter() == mCurrentPrinter) {
                        confirmPrint();
                    } else {
                        ApprovedPrintServices approvedServices =
                                new ApprovedPrintServices(PrintActivity.this);

                        ComponentName printService = mCurrentPrinter.getId().getServiceName();
                        if (approvedServices.isApprovedService(printService)) {
                            confirmPrint();
                        } else {
                            PrintServiceApprovalDialog.newInstance(printService)
                                    .show(getFragmentManager(), "approve");
                        }
                    }
                } else {
                    cancelPrint();
                }
            } else if (view == mMoreOptionsButton) {
                if (mPageRangeEditText.getError() == null) {
                    // The selected pages is only applied once the user leaves the text field. A click
                    // on this button, does not count as leaving.
                    updateSelectedPagesFromTextField();
                }

                if (mCurrentPrinter != null) {
                    startAdvancedPrintOptionsActivity(mCurrentPrinter);
                }
            }
        }
    }

    private static boolean canPrint(PrinterInfo printer) {
        return printer.getCapabilities() != null
                && printer.getStatus() != PrinterInfo.STATUS_UNAVAILABLE;
    }

    /**
     * Disable all options UI elements, beside the {@link #mDestinationSpinner}
     */
    private void disableOptionsUi() {
        mCopiesEditText.setEnabled(false);
        mCopiesEditText.setFocusable(false);
        mMediaSizeSpinner.setEnabled(false);
        mColorModeSpinner.setEnabled(false);
        mDuplexModeSpinner.setEnabled(false);
        mOrientationSpinner.setEnabled(false);
        mRangeOptionsSpinner.setEnabled(false);
        mPageRangeEditText.setEnabled(false);
        mPrintButton.setVisibility(View.GONE);
        mMoreOptionsButton.setEnabled(false);
    }

    void updateOptionsUi() {
        if (!mIsOptionsUiBound) {
            return;
        }

        // Always update the summary.
        updateSummary();

        if (mState == STATE_PRINT_CONFIRMED
                || mState == STATE_PRINT_COMPLETED
                || mState == STATE_PRINT_CANCELED
                || mState == STATE_UPDATE_FAILED
                || mState == STATE_CREATE_FILE_FAILED
                || mState == STATE_PRINTER_UNAVAILABLE
                || mState == STATE_UPDATE_SLOW) {
            if (mState != STATE_PRINTER_UNAVAILABLE) {
                mDestinationSpinner.setEnabled(false);
            }
            disableOptionsUi();
            return;
        }

        // If no current printer, or it has no capabilities, or it is not
        // available, we disable all print options except the destination.
        if (mCurrentPrinter == null || !canPrint(mCurrentPrinter)) {
            disableOptionsUi();
            return;
        }

        PrinterCapabilitiesInfo capabilities = mCurrentPrinter.getCapabilities();
        PrintAttributes defaultAttributes = capabilities.getDefaults();

        // Destination.
        mDestinationSpinner.setEnabled(true);

        // Media size.
        mMediaSizeSpinner.setEnabled(true);

        List<MediaSize> mediaSizes = new ArrayList<>(capabilities.getMediaSizes());
        // Sort the media sizes based on the current locale.
        Collections.sort(mediaSizes, mMediaSizeComparator);

        PrintAttributes attributes = mPrintJob.getAttributes();

        // If the media sizes changed, we update the adapter and the spinner.
        boolean mediaSizesChanged = false;
        final int mediaSizeCount = mediaSizes.size();
        if (mediaSizeCount != mMediaSizeSpinnerAdapter.getCount()) {
            mediaSizesChanged = true;
        } else {
            for (int i = 0; i < mediaSizeCount; i++) {
                if (!mediaSizes.get(i).equals(mMediaSizeSpinnerAdapter.getItem(i).value)) {
                    mediaSizesChanged = true;
                    break;
                }
            }
        }
        if (mediaSizesChanged) {
            // Remember the old media size to try selecting it again.
            int oldMediaSizeNewIndex = AdapterView.INVALID_POSITION;
            MediaSize oldMediaSize = attributes.getMediaSize();

            // Rebuild the adapter data.
            mMediaSizeSpinnerAdapter.clear();
            for (int i = 0; i < mediaSizeCount; i++) {
                MediaSize mediaSize = mediaSizes.get(i);
                if (oldMediaSize != null
                        && mediaSize.asPortrait().equals(oldMediaSize.asPortrait())) {
                    // Update the index of the old selection.
                    oldMediaSizeNewIndex = i;
                }
                mMediaSizeSpinnerAdapter.add(new SpinnerItem<>(
                        mediaSize, mediaSize.getLabel(getPackageManager())));
            }

            if (oldMediaSizeNewIndex != AdapterView.INVALID_POSITION) {
                // Select the old media size - nothing really changed.
                if (mMediaSizeSpinner.getSelectedItemPosition() != oldMediaSizeNewIndex) {
                    mMediaSizeSpinner.setSelection(oldMediaSizeNewIndex);
                }
            } else {
                // Select the first or the default.
                final int mediaSizeIndex = Math.max(mediaSizes.indexOf(
                        defaultAttributes.getMediaSize()), 0);
                if (mMediaSizeSpinner.getSelectedItemPosition() != mediaSizeIndex) {
                    mMediaSizeSpinner.setSelection(mediaSizeIndex);
                }
                // Respect the orientation of the old selection.
                if (oldMediaSize != null) {
                    if (oldMediaSize.isPortrait()) {
                        attributes.setMediaSize(mMediaSizeSpinnerAdapter
                                .getItem(mediaSizeIndex).value.asPortrait());
                    } else {
                        attributes.setMediaSize(mMediaSizeSpinnerAdapter
                                .getItem(mediaSizeIndex).value.asLandscape());
                    }
                }
            }
        }

        // Color mode.
        mColorModeSpinner.setEnabled(true);
        final int colorModes = capabilities.getColorModes();

        // If the color modes changed, we update the adapter and the spinner.
        boolean colorModesChanged = false;
        if (Integer.bitCount(colorModes) != mColorModeSpinnerAdapter.getCount()) {
            colorModesChanged = true;
        } else {
            int remainingColorModes = colorModes;
            int adapterIndex = 0;
            while (remainingColorModes != 0) {
                final int colorBitOffset = Integer.numberOfTrailingZeros(remainingColorModes);
                final int colorMode = 1 << colorBitOffset;
                remainingColorModes &= ~colorMode;
                if (colorMode != mColorModeSpinnerAdapter.getItem(adapterIndex).value) {
                    colorModesChanged = true;
                    break;
                }
                adapterIndex++;
            }
        }
        if (colorModesChanged) {
            // Remember the old color mode to try selecting it again.
            int oldColorModeNewIndex = AdapterView.INVALID_POSITION;
            final int oldColorMode = attributes.getColorMode();

            // Rebuild the adapter data.
            mColorModeSpinnerAdapter.clear();
            String[] colorModeLabels = getResources().getStringArray(R.array.color_mode_labels);
            int remainingColorModes = colorModes;
            while (remainingColorModes != 0) {
                final int colorBitOffset = Integer.numberOfTrailingZeros(remainingColorModes);
                final int colorMode = 1 << colorBitOffset;
                if (colorMode == oldColorMode) {
                    // Update the index of the old selection.
                    oldColorModeNewIndex = mColorModeSpinnerAdapter.getCount();
                }
                remainingColorModes &= ~colorMode;
                mColorModeSpinnerAdapter.add(new SpinnerItem<>(colorMode,
                        colorModeLabels[colorBitOffset]));
            }
            if (oldColorModeNewIndex != AdapterView.INVALID_POSITION) {
                // Select the old color mode - nothing really changed.
                if (mColorModeSpinner.getSelectedItemPosition() != oldColorModeNewIndex) {
                    mColorModeSpinner.setSelection(oldColorModeNewIndex);
                }
            } else {
                // Select the default.
                final int selectedColorMode = colorModes & defaultAttributes.getColorMode();
                final int itemCount = mColorModeSpinnerAdapter.getCount();
                for (int i = 0; i < itemCount; i++) {
                    SpinnerItem<Integer> item = mColorModeSpinnerAdapter.getItem(i);
                    if (selectedColorMode == item.value) {
                        if (mColorModeSpinner.getSelectedItemPosition() != i) {
                            mColorModeSpinner.setSelection(i);
                        }
                        attributes.setColorMode(selectedColorMode);
                        break;
                    }
                }
            }
        }

        // Duplex mode.
        mDuplexModeSpinner.setEnabled(true);
        final int duplexModes = capabilities.getDuplexModes();

        // If the duplex modes changed, we update the adapter and the spinner.
        // Note that we use bit count +1 to account for the no duplex option.
        boolean duplexModesChanged = false;
        if (Integer.bitCount(duplexModes) != mDuplexModeSpinnerAdapter.getCount()) {
            duplexModesChanged = true;
        } else {
            int remainingDuplexModes = duplexModes;
            int adapterIndex = 0;
            while (remainingDuplexModes != 0) {
                final int duplexBitOffset = Integer.numberOfTrailingZeros(remainingDuplexModes);
                final int duplexMode = 1 << duplexBitOffset;
                remainingDuplexModes &= ~duplexMode;
                if (duplexMode != mDuplexModeSpinnerAdapter.getItem(adapterIndex).value) {
                    duplexModesChanged = true;
                    break;
                }
                adapterIndex++;
            }
        }
        if (duplexModesChanged) {
            // Remember the old duplex mode to try selecting it again. Also the fallback
            // is no duplexing which is always the first item in the dropdown.
            int oldDuplexModeNewIndex = AdapterView.INVALID_POSITION;
            final int oldDuplexMode = attributes.getDuplexMode();

            // Rebuild the adapter data.
            mDuplexModeSpinnerAdapter.clear();
            String[] duplexModeLabels = getResources().getStringArray(R.array.duplex_mode_labels);
            int remainingDuplexModes = duplexModes;
            while (remainingDuplexModes != 0) {
                final int duplexBitOffset = Integer.numberOfTrailingZeros(remainingDuplexModes);
                final int duplexMode = 1 << duplexBitOffset;
                if (duplexMode == oldDuplexMode) {
                    // Update the index of the old selection.
                    oldDuplexModeNewIndex = mDuplexModeSpinnerAdapter.getCount();
                }
                remainingDuplexModes &= ~duplexMode;
                mDuplexModeSpinnerAdapter.add(new SpinnerItem<>(duplexMode,
                        duplexModeLabels[duplexBitOffset]));
            }

            if (oldDuplexModeNewIndex != AdapterView.INVALID_POSITION) {
                // Select the old duplex mode - nothing really changed.
                if (mDuplexModeSpinner.getSelectedItemPosition() != oldDuplexModeNewIndex) {
                    mDuplexModeSpinner.setSelection(oldDuplexModeNewIndex);
                }
            } else {
                // Select the default.
                final int selectedDuplexMode = defaultAttributes.getDuplexMode();
                final int itemCount = mDuplexModeSpinnerAdapter.getCount();
                for (int i = 0; i < itemCount; i++) {
                    SpinnerItem<Integer> item = mDuplexModeSpinnerAdapter.getItem(i);
                    if (selectedDuplexMode == item.value) {
                        if (mDuplexModeSpinner.getSelectedItemPosition() != i) {
                            mDuplexModeSpinner.setSelection(i);
                        }
                        attributes.setDuplexMode(selectedDuplexMode);
                        break;
                    }
                }
            }
        }

        mDuplexModeSpinner.setEnabled(mDuplexModeSpinnerAdapter.getCount() > 1);

        // Orientation
        mOrientationSpinner.setEnabled(true);
        MediaSize mediaSize = attributes.getMediaSize();
        if (mediaSize != null) {
            if (mediaSize.isPortrait()
                    && mOrientationSpinner.getSelectedItemPosition() != 0) {
                mOrientationSpinner.setSelection(0);
            } else if (!mediaSize.isPortrait()
                    && mOrientationSpinner.getSelectedItemPosition() != 1) {
                mOrientationSpinner.setSelection(1);
            }
        }

        // Range options
        PrintDocumentInfo info = mPrintedDocument.getDocumentInfo().info;
        final int pageCount = getAdjustedPageCount(info);
        if (pageCount > 0) {
            if (info != null) {
                if (pageCount == 1) {
                    mRangeOptionsSpinner.setEnabled(false);
                } else {
                    mRangeOptionsSpinner.setEnabled(true);
                    if (mRangeOptionsSpinner.getSelectedItemPosition() > 0) {
                        if (!mPageRangeEditText.isEnabled()) {
                            mPageRangeEditText.setEnabled(true);
                            mPageRangeEditText.setVisibility(View.VISIBLE);
                            mPageRangeTitle.setVisibility(View.VISIBLE);
                            mPageRangeEditText.requestFocus();
                            InputMethodManager imm = (InputMethodManager)
                                    getSystemService(Context.INPUT_METHOD_SERVICE);
                            imm.showSoftInput(mPageRangeEditText, 0);
                        }
                    } else {
                        mPageRangeEditText.setEnabled(false);
                        mPageRangeEditText.setVisibility(View.INVISIBLE);
                        mPageRangeTitle.setVisibility(View.INVISIBLE);
                    }
                }
            } else {
                if (mRangeOptionsSpinner.getSelectedItemPosition() != 0) {
                    mRangeOptionsSpinner.setSelection(0);
                    mPageRangeEditText.setText("");
                }
                mRangeOptionsSpinner.setEnabled(false);
                mPageRangeEditText.setEnabled(false);
                mPageRangeEditText.setVisibility(View.INVISIBLE);
                mPageRangeTitle.setVisibility(View.INVISIBLE);
            }
        }

        final int newPageCount = getAdjustedPageCount(info);
        if (newPageCount != mCurrentPageCount) {
            mCurrentPageCount = newPageCount;
            updatePageRangeOptions(newPageCount);
        }

        // Advanced print options
        if (mAdvancedPrintOptionsActivity != null) {
            mMoreOptionsButton.setVisibility(View.VISIBLE);
            mMoreOptionsButton.setEnabled(true);
        } else {
            mMoreOptionsButton.setVisibility(View.GONE);
            mMoreOptionsButton.setEnabled(false);
        }

        // Print
        if (mDestinationSpinnerAdapter.getPdfPrinter() != mCurrentPrinter) {
            mPrintButton.setImageResource(com.android.internal.R.drawable.ic_print);
            mPrintButton.setContentDescription(getString(R.string.print_button));
        } else {
            mPrintButton.setImageResource(R.drawable.ic_menu_savetopdf);
            mPrintButton.setContentDescription(getString(R.string.savetopdf_button));
        }
        if (!mPrintedDocument.getDocumentInfo().laidout
                ||(mRangeOptionsSpinner.getSelectedItemPosition() == 1
                && (TextUtils.isEmpty(mPageRangeEditText.getText()) || hasErrors()))
                || (mRangeOptionsSpinner.getSelectedItemPosition() == 0
                && (mPrintedDocument.getDocumentInfo() == null || hasErrors()))) {
            mPrintButton.setVisibility(View.GONE);
        } else {
            mPrintButton.setVisibility(View.VISIBLE);
        }

        // Copies
        if (mDestinationSpinnerAdapter.getPdfPrinter() != mCurrentPrinter) {
            mCopiesEditText.setEnabled(true);
            mCopiesEditText.setFocusableInTouchMode(true);
        } else {
            CharSequence text = mCopiesEditText.getText();
            if (TextUtils.isEmpty(text) || !MIN_COPIES_STRING.equals(text.toString())) {
                mCopiesEditText.setText(MIN_COPIES_STRING);
            }
            mCopiesEditText.setEnabled(false);
            mCopiesEditText.setFocusable(false);
        }
        if (mCopiesEditText.getError() == null
                && TextUtils.isEmpty(mCopiesEditText.getText())) {
            mCopiesEditText.setText(MIN_COPIES_STRING);
            mCopiesEditText.requestFocus();
        }

        if (mShowDestinationPrompt) {
            disableOptionsUi();
        }
    }

    private void updateSummary() {
        if (!mIsOptionsUiBound) {
            return;
        }

        CharSequence copiesText = null;
        CharSequence mediaSizeText = null;

        if (!TextUtils.isEmpty(mCopiesEditText.getText())) {
            copiesText = mCopiesEditText.getText();
            mSummaryCopies.setText(copiesText);
        }

        final int selectedMediaIndex = mMediaSizeSpinner.getSelectedItemPosition();
        if (selectedMediaIndex >= 0) {
            SpinnerItem<MediaSize> mediaItem = mMediaSizeSpinnerAdapter.getItem(selectedMediaIndex);
            mediaSizeText = mediaItem.label;
            mSummaryPaperSize.setText(mediaSizeText);
        }

        if (!TextUtils.isEmpty(copiesText) && !TextUtils.isEmpty(mediaSizeText)) {
            String summaryText = getString(R.string.summary_template, copiesText, mediaSizeText);
            mSummaryContainer.setContentDescription(summaryText);
        }
    }

    private void updatePageRangeOptions(int pageCount) {
        @SuppressWarnings("unchecked")
        ArrayAdapter<SpinnerItem<Integer>> rangeOptionsSpinnerAdapter =
                (ArrayAdapter<SpinnerItem<Integer>>) mRangeOptionsSpinner.getAdapter();
        rangeOptionsSpinnerAdapter.clear();

        final int[] rangeOptionsValues = getResources().getIntArray(
                R.array.page_options_values);

        String pageCountLabel = (pageCount > 0) ? String.valueOf(pageCount) : "";
        String[] rangeOptionsLabels = new String[] {
            getString(R.string.template_all_pages, pageCountLabel),
            getString(R.string.template_page_range, pageCountLabel)
        };

        final int rangeOptionsCount = rangeOptionsLabels.length;
        for (int i = 0; i < rangeOptionsCount; i++) {
            rangeOptionsSpinnerAdapter.add(new SpinnerItem<>(
                    rangeOptionsValues[i], rangeOptionsLabels[i]));
        }
    }

    private PageRange[] computeSelectedPages() {
        if (hasErrors()) {
            return null;
        }

        if (mRangeOptionsSpinner.getSelectedItemPosition() > 0) {
            PrintDocumentInfo info = mPrintedDocument.getDocumentInfo().info;
            final int pageCount = (info != null) ? getAdjustedPageCount(info) : 0;

            return PageRangeUtils.parsePageRanges(mPageRangeEditText.getText(), pageCount);
        }

        return PageRange.ALL_PAGES_ARRAY;
    }

    private int getAdjustedPageCount(PrintDocumentInfo info) {
        if (info != null) {
            final int pageCount = info.getPageCount();
            if (pageCount != PrintDocumentInfo.PAGE_COUNT_UNKNOWN) {
                return pageCount;
            }
        }
        // If the app does not tell us how many pages are in the
        // doc we ask for all pages and use the document page count.
        return mPrintPreviewController.getFilePageCount();
    }

    private boolean hasErrors() {
        return (mCopiesEditText.getError() != null)
                || (mPageRangeEditText.getVisibility() == View.VISIBLE
                && mPageRangeEditText.getError() != null);
    }

    public void onPrinterAvailable(PrinterInfo printer) {
        if (mCurrentPrinter != null && mCurrentPrinter.equals(printer)) {
            setState(STATE_CONFIGURING);
            if (canUpdateDocument()) {
                updateDocument(false);
            }
            ensurePreviewUiShown();
            updateOptionsUi();
        }
    }

    public void onPrinterUnavailable(PrinterInfo printer) {
        if (mCurrentPrinter.getId().equals(printer.getId())) {
            setState(STATE_PRINTER_UNAVAILABLE);
            mPrintedDocument.cancel(false);
            ensureErrorUiShown(getString(R.string.print_error_printer_unavailable),
                    PrintErrorFragment.ACTION_NONE);
            updateOptionsUi();
        }
    }

    private boolean canUpdateDocument() {
        if (mPrintedDocument.isDestroyed()) {
            return false;
        }

        if (hasErrors()) {
            return false;
        }

        PrintAttributes attributes = mPrintJob.getAttributes();

        final int colorMode = attributes.getColorMode();
        if (colorMode != PrintAttributes.COLOR_MODE_COLOR
                && colorMode != PrintAttributes.COLOR_MODE_MONOCHROME) {
            return false;
        }
        if (attributes.getMediaSize() == null) {
            return false;
        }
        if (attributes.getMinMargins() == null) {
            return false;
        }
        if (attributes.getResolution() == null) {
            return false;
        }

        if (mCurrentPrinter == null) {
            return false;
        }
        PrinterCapabilitiesInfo capabilities = mCurrentPrinter.getCapabilities();
        if (capabilities == null) {
            return false;
        }
        if (mCurrentPrinter.getStatus() == PrinterInfo.STATUS_UNAVAILABLE) {
            return false;
        }

        return true;
    }

    private void transformDocumentAndFinish(final Uri writeToUri) {
        // If saving to PDF, apply the attibutes as we are acting as a print service.
        PrintAttributes attributes = mDestinationSpinnerAdapter.getPdfPrinter() == mCurrentPrinter
                ?  mPrintJob.getAttributes() : null;
        new DocumentTransformer(this, mPrintJob, mFileProvider, attributes, new Runnable() {
            @Override
            public void run() {
                if (writeToUri != null) {
                    mPrintedDocument.writeContent(getContentResolver(), writeToUri);
                }
                setState(STATE_PRINT_COMPLETED);
                doFinish();
            }
        }).transform();
    }

    private void doFinish() {
        if (mPrintedDocument != null && mPrintedDocument.isUpdating()) {
            // The printedDocument will call doFinish() when the current command finishes
            return;
        }

        if (mIsFinishing) {
            return;
        }

        mIsFinishing = true;

        if (mPrinterRegistry != null) {
            mPrinterRegistry.setTrackedPrinter(null);
            mPrinterRegistry.setOnPrintersChangeListener(null);
        }

        if (mPrintersObserver != null) {
            mDestinationSpinnerAdapter.unregisterDataSetObserver(mPrintersObserver);
        }

        if (mSpoolerProvider != null) {
            mSpoolerProvider.destroy();
        }

        if (mProgressMessageController != null) {
            setState(mProgressMessageController.cancel());
        }

        if (mState != STATE_INITIALIZING) {
            mPrintedDocument.finish();
            mPrintedDocument.destroy();
            mPrintPreviewController.destroy(new Runnable() {
                @Override
                public void run() {
                    finish();
                }
            });
        } else {
            finish();
        }
    }

    private final class SpinnerItem<T> {
        final T value;
        final CharSequence label;

        public SpinnerItem(T value, CharSequence label) {
            this.value = value;
            this.label = label;
        }

        @Override
        public String toString() {
            return label.toString();
        }
    }

    private final class PrinterAvailabilityDetector implements Runnable {
        private static final long UNAVAILABLE_TIMEOUT_MILLIS = 10000; // 10sec

        private boolean mPosted;

        private boolean mPrinterUnavailable;

        private PrinterInfo mPrinter;

        public void updatePrinter(PrinterInfo printer) {
            if (printer.equals(mDestinationSpinnerAdapter.getPdfPrinter())) {
                return;
            }

            final boolean available = printer.getStatus() != PrinterInfo.STATUS_UNAVAILABLE
                    && printer.getCapabilities() != null;
            final boolean notifyIfAvailable;

            if (mPrinter == null || !mPrinter.getId().equals(printer.getId())) {
                notifyIfAvailable = true;
                unpostIfNeeded();
                mPrinterUnavailable = false;
                mPrinter = new PrinterInfo.Builder(printer).build();
            } else {
                notifyIfAvailable =
                        (mPrinter.getStatus() == PrinterInfo.STATUS_UNAVAILABLE
                                && printer.getStatus() != PrinterInfo.STATUS_UNAVAILABLE)
                                || (mPrinter.getCapabilities() == null
                                && printer.getCapabilities() != null);
                mPrinter = printer;
            }

            if (available) {
                unpostIfNeeded();
                mPrinterUnavailable = false;
                if (notifyIfAvailable) {
                    onPrinterAvailable(mPrinter);
                }
            } else {
                if (!mPrinterUnavailable) {
                    postIfNeeded();
                }
            }
        }

        public void cancel() {
            unpostIfNeeded();
            mPrinterUnavailable = false;
        }

        private void postIfNeeded() {
            if (!mPosted) {
                mPosted = true;
                mDestinationSpinner.postDelayed(this, UNAVAILABLE_TIMEOUT_MILLIS);
            }
        }

        private void unpostIfNeeded() {
            if (mPosted) {
                mPosted = false;
                mDestinationSpinner.removeCallbacks(this);
            }
        }

        @Override
        public void run() {
            mPosted = false;
            mPrinterUnavailable = true;
            onPrinterUnavailable(mPrinter);
        }
    }

    private static final class PrinterHolder {
        PrinterInfo printer;
        boolean removed;

        public PrinterHolder(PrinterInfo printer) {
            this.printer = printer;
        }
    }


    /**
     * Check if the user has ever printed a document
     *
     * @return true iff the user has ever printed a document
     */
    private boolean hasUserEverPrinted() {
        SharedPreferences preferences = getSharedPreferences(HAS_PRINTED_PREF, MODE_PRIVATE);

        return preferences.getBoolean(HAS_PRINTED_PREF, false);
    }

    /**
     * Remember that the user printed a document
     */
    private void setUserPrinted() {
        SharedPreferences preferences = getSharedPreferences(HAS_PRINTED_PREF, MODE_PRIVATE);

        if (!preferences.getBoolean(HAS_PRINTED_PREF, false)) {
            SharedPreferences.Editor edit = preferences.edit();

            edit.putBoolean(HAS_PRINTED_PREF, true);
            edit.apply();
        }
    }

    private final class DestinationAdapter extends BaseAdapter
            implements PrinterRegistry.OnPrintersChangeListener {
        private final List<PrinterHolder> mPrinterHolders = new ArrayList<>();

        private final PrinterHolder mFakePdfPrinterHolder;

        private boolean mHistoricalPrintersLoaded;

        /**
         * Has the {@link #mDestinationSpinner} ever used a view from printer_dropdown_prompt
         */
        private boolean hadPromptView;

        public DestinationAdapter() {
            mHistoricalPrintersLoaded = mPrinterRegistry.areHistoricalPrintersLoaded();
            if (mHistoricalPrintersLoaded) {
                addPrinters(mPrinterHolders, mPrinterRegistry.getPrinters());
            }
            mPrinterRegistry.setOnPrintersChangeListener(this);
            mFakePdfPrinterHolder = new PrinterHolder(createFakePdfPrinter());
        }

        public PrinterInfo getPdfPrinter() {
            return mFakePdfPrinterHolder.printer;
        }

        public int getPrinterIndex(PrinterId printerId) {
            for (int i = 0; i < getCount(); i++) {
                PrinterHolder printerHolder = (PrinterHolder) getItem(i);
                if (printerHolder != null && !printerHolder.removed
                        && printerHolder.printer.getId().equals(printerId)) {
                    return i;
                }
            }
            return AdapterView.INVALID_POSITION;
        }

        public void ensurePrinterInVisibleAdapterPosition(PrinterInfo printer) {
            final int printerCount = mPrinterHolders.size();
            boolean isKnownPrinter = false;
            for (int i = 0; i < printerCount; i++) {
                PrinterHolder printerHolder = mPrinterHolders.get(i);

                if (printerHolder.printer.getId().equals(printer.getId())) {
                    isKnownPrinter = true;

                    // If already in the list - do nothing.
                    if (i < getCount() - 2) {
                        break;
                    }
                    // Else replace the last one (two items are not printers).
                    final int lastPrinterIndex = getCount() - 3;
                    mPrinterHolders.set(i, mPrinterHolders.get(lastPrinterIndex));
                    mPrinterHolders.set(lastPrinterIndex, printerHolder);
                    break;
                }
            }

            if (!isKnownPrinter) {
                PrinterHolder printerHolder = new PrinterHolder(printer);
                printerHolder.removed = true;

                mPrinterHolders.add(Math.max(0, getCount() - 3), printerHolder);
            }

            // Force reload to adjust selection in PrintersObserver.onChanged()
            notifyDataSetChanged();
        }

        @Override
        public int getCount() {
            if (mHistoricalPrintersLoaded) {
                return Math.min(mPrinterHolders.size() + 2, DEST_ADAPTER_MAX_ITEM_COUNT);
            }
            return 0;
        }

        @Override
        public boolean isEnabled(int position) {
            Object item = getItem(position);
            if (item instanceof PrinterHolder) {
                PrinterHolder printerHolder = (PrinterHolder) item;
                return !printerHolder.removed
                        && printerHolder.printer.getStatus() != PrinterInfo.STATUS_UNAVAILABLE;
            }
            return true;
        }

        @Override
        public Object getItem(int position) {
            if (mPrinterHolders.isEmpty()) {
                if (position == 0) {
                    return mFakePdfPrinterHolder;
                }
            } else {
                if (position < 1) {
                    return mPrinterHolders.get(position);
                }
                if (position == 1) {
                    return mFakePdfPrinterHolder;
                }
                if (position < getCount() - 1) {
                    return mPrinterHolders.get(position - 1);
                }
            }
            return null;
        }

        @Override
        public long getItemId(int position) {
            if (mPrinterHolders.isEmpty()) {
                if (position == 0) {
                    return DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF;
                } else if (position == 1) {
                    return DEST_ADAPTER_ITEM_ID_MORE;
                }
            } else {
                if (position == 1) {
                    return DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF;
                }
                if (position == getCount() - 1) {
                    return DEST_ADAPTER_ITEM_ID_MORE;
                }
            }
            return position;
        }

        @Override
        public View getDropDownView(int position, View convertView, ViewGroup parent) {
            View view = getView(position, convertView, parent);
            view.setEnabled(isEnabled(position));
            return view;
        }

        private String getMoreItemTitle() {
            if (mArePrintServicesEnabled) {
                return getString(R.string.all_printers);
            } else {
                return getString(R.string.print_add_printer);
            }
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (mShowDestinationPrompt) {
                if (convertView == null) {
                    convertView = getLayoutInflater().inflate(
                            R.layout.printer_dropdown_prompt, parent, false);
                    hadPromptView = true;
                }

                return convertView;
            } else {
                // We don't know if we got an recyled printer_dropdown_prompt, hence do not use it
                if (hadPromptView || convertView == null) {
                    convertView = getLayoutInflater().inflate(
                            R.layout.printer_dropdown_item, parent, false);
                }
            }

            CharSequence title = null;
            CharSequence subtitle = null;
            Drawable icon = null;

            if (mPrinterHolders.isEmpty()) {
                if (position == 0 && getPdfPrinter() != null) {
                    PrinterHolder printerHolder = (PrinterHolder) getItem(position);
                    title = printerHolder.printer.getName();
                    icon = getResources().getDrawable(R.drawable.ic_menu_savetopdf, null);
                } else if (position == 1) {
                    title = getMoreItemTitle();
                }
            } else {
                if (position == 1 && getPdfPrinter() != null) {
                    PrinterHolder printerHolder = (PrinterHolder) getItem(position);
                    title = printerHolder.printer.getName();
                    icon = getResources().getDrawable(R.drawable.ic_menu_savetopdf, null);
                } else if (position == getCount() - 1) {
                    title = getMoreItemTitle();
                } else {
                    PrinterHolder printerHolder = (PrinterHolder) getItem(position);
                    PrinterInfo printInfo = printerHolder.printer;

                    title = printInfo.getName();
                    icon = printInfo.loadIcon(PrintActivity.this);
                    subtitle = printInfo.getDescription();
                }
            }

            TextView titleView = (TextView) convertView.findViewById(R.id.title);
            titleView.setText(title);

            TextView subtitleView = (TextView) convertView.findViewById(R.id.subtitle);
            if (!TextUtils.isEmpty(subtitle)) {
                subtitleView.setText(subtitle);
                subtitleView.setVisibility(View.VISIBLE);
            } else {
                subtitleView.setText(null);
                subtitleView.setVisibility(View.GONE);
            }

            ImageView iconView = (ImageView) convertView.findViewById(R.id.icon);
            if (icon != null) {
                iconView.setVisibility(View.VISIBLE);
                if (!isEnabled(position)) {
                    icon.mutate();

                    TypedValue value = new TypedValue();
                    getTheme().resolveAttribute(android.R.attr.disabledAlpha, value, true);
                    icon.setAlpha((int)(value.getFloat() * 255));
                }
                iconView.setImageDrawable(icon);
            } else {
                iconView.setVisibility(View.INVISIBLE);
            }

            return convertView;
        }

        @Override
        public void onPrintersChanged(List<PrinterInfo> printers) {
            // We rearrange the printers if the user selects a printer
            // not shown in the initial short list. Therefore, we have
            // to keep the printer order.

            // Check if historical printers are loaded as this adapter is open
            // for busyness only if they are. This member is updated here and
            // when the adapter is created because the historical printers may
            // be loaded before or after the adapter is created.
            mHistoricalPrintersLoaded = mPrinterRegistry.areHistoricalPrintersLoaded();

            // No old printers - do not bother keeping their position.
            if (mPrinterHolders.isEmpty()) {
                addPrinters(mPrinterHolders, printers);
                notifyDataSetChanged();
                return;
            }

            // Add the new printers to a map.
            ArrayMap<PrinterId, PrinterInfo> newPrintersMap = new ArrayMap<>();
            final int printerCount = printers.size();
            for (int i = 0; i < printerCount; i++) {
                PrinterInfo printer = printers.get(i);
                newPrintersMap.put(printer.getId(), printer);
            }

            List<PrinterHolder> newPrinterHolders = new ArrayList<>();

            // Update printers we already have which are either updated or removed.
            // We do not remove the currently selected printer.
            final int oldPrinterCount = mPrinterHolders.size();
            for (int i = 0; i < oldPrinterCount; i++) {
                PrinterHolder printerHolder = mPrinterHolders.get(i);
                PrinterId oldPrinterId = printerHolder.printer.getId();
                PrinterInfo updatedPrinter = newPrintersMap.remove(oldPrinterId);

                if (updatedPrinter != null) {
                    printerHolder.printer = updatedPrinter;
                    printerHolder.removed = false;
                    onPrinterAvailable(printerHolder.printer);
                    newPrinterHolders.add(printerHolder);
                } else if (mCurrentPrinter != null && mCurrentPrinter.getId().equals(oldPrinterId)){
                    printerHolder.removed = true;
                    onPrinterUnavailable(printerHolder.printer);
                    newPrinterHolders.add(printerHolder);
                }
            }

            // Add the rest of the new printers, i.e. what is left.
            addPrinters(newPrinterHolders, newPrintersMap.values());

            mPrinterHolders.clear();
            mPrinterHolders.addAll(newPrinterHolders);

            notifyDataSetChanged();
        }

        @Override
        public void onPrintersInvalid() {
            mPrinterHolders.clear();
            notifyDataSetInvalidated();
        }

        public PrinterHolder getPrinterHolder(PrinterId printerId) {
            final int itemCount = getCount();
            for (int i = 0; i < itemCount; i++) {
                Object item = getItem(i);
                if (item instanceof PrinterHolder) {
                    PrinterHolder printerHolder = (PrinterHolder) item;
                    if (printerId.equals(printerHolder.printer.getId())) {
                        return printerHolder;
                    }
                }
            }
            return null;
        }

        /**
         * Remove a printer from the holders if it is marked as removed.
         *
         * @param printerId the id of the printer to remove.
         *
         * @return true iff the printer was removed.
         */
        public boolean pruneRemovedPrinter(PrinterId printerId) {
            final int holderCounts = mPrinterHolders.size();
            for (int i = holderCounts - 1; i >= 0; i--) {
                PrinterHolder printerHolder = mPrinterHolders.get(i);

                if (printerHolder.printer.getId().equals(printerId) && printerHolder.removed) {
                    mPrinterHolders.remove(i);
                    return true;
                }
            }

            return false;
        }

        private void addPrinters(List<PrinterHolder> list, Collection<PrinterInfo> printers) {
            for (PrinterInfo printer : printers) {
                PrinterHolder printerHolder = new PrinterHolder(printer);
                list.add(printerHolder);
            }
        }

        private PrinterInfo createFakePdfPrinter() {
            ArraySet<MediaSize> allMediaSizes = MediaSize.getAllPredefinedSizes();
            MediaSize defaultMediaSize = MediaSizeUtils.getDefault(PrintActivity.this);

            PrinterId printerId = new PrinterId(getComponentName(), "PDF printer");

            PrinterCapabilitiesInfo.Builder builder =
                    new PrinterCapabilitiesInfo.Builder(printerId);

            final int mediaSizeCount = allMediaSizes.size();
            for (int i = 0; i < mediaSizeCount; i++) {
                MediaSize mediaSize = allMediaSizes.valueAt(i);
                builder.addMediaSize(mediaSize, mediaSize.equals(defaultMediaSize));
            }

            builder.addResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300),
                    true);
            builder.setColorModes(PrintAttributes.COLOR_MODE_COLOR
                    | PrintAttributes.COLOR_MODE_MONOCHROME, PrintAttributes.COLOR_MODE_COLOR);

            return new PrinterInfo.Builder(printerId, getString(R.string.save_as_pdf),
                    PrinterInfo.STATUS_IDLE).setCapabilities(builder.build()).build();
        }
    }

    private final class PrintersObserver extends DataSetObserver {
        @Override
        public void onChanged() {
            PrinterInfo oldPrinterState = mCurrentPrinter;
            if (oldPrinterState == null) {
                return;
            }

            PrinterHolder printerHolder = mDestinationSpinnerAdapter.getPrinterHolder(
                    oldPrinterState.getId());
            PrinterInfo newPrinterState = printerHolder.printer;

            if (printerHolder.removed) {
                onPrinterUnavailable(newPrinterState);
            }

            if (mDestinationSpinner.getSelectedItem() != printerHolder) {
                mDestinationSpinner.setSelection(
                        mDestinationSpinnerAdapter.getPrinterIndex(newPrinterState.getId()));
            }

            if (oldPrinterState.equals(newPrinterState)) {
                return;
            }

            PrinterCapabilitiesInfo oldCapab = oldPrinterState.getCapabilities();
            PrinterCapabilitiesInfo newCapab = newPrinterState.getCapabilities();

            final boolean hadCabab = oldCapab != null;
            final boolean hasCapab = newCapab != null;
            final boolean gotCapab = oldCapab == null && newCapab != null;
            final boolean lostCapab = oldCapab != null && newCapab == null;
            final boolean capabChanged = capabilitiesChanged(oldCapab, newCapab);

            final int oldStatus = oldPrinterState.getStatus();
            final int newStatus = newPrinterState.getStatus();

            final boolean isActive = newStatus != PrinterInfo.STATUS_UNAVAILABLE;
            final boolean becameActive = (oldStatus == PrinterInfo.STATUS_UNAVAILABLE
                    && oldStatus != newStatus);
            final boolean becameInactive = (newStatus == PrinterInfo.STATUS_UNAVAILABLE
                    && oldStatus != newStatus);

            mPrinterAvailabilityDetector.updatePrinter(newPrinterState);

            mCurrentPrinter = newPrinterState;

            final boolean updateNeeded = ((capabChanged && hasCapab && isActive)
                    || (becameActive && hasCapab) || (isActive && gotCapab));

            if (capabChanged && hasCapab) {
                updatePrintAttributesFromCapabilities(newCapab);
            }

            if (updateNeeded) {
                updatePrintPreviewController(false);
            }

            if ((isActive && gotCapab) || (becameActive && hasCapab)) {
                onPrinterAvailable(newPrinterState);
            } else if ((becameInactive && hadCabab) || (isActive && lostCapab)) {
                onPrinterUnavailable(newPrinterState);
            }

            if (updateNeeded && canUpdateDocument()) {
                updateDocument(false);
            }

            // Force a reload of the enabled print services to update mAdvancedPrintOptionsActivity
            // in onLoadFinished();
            getLoaderManager().getLoader(LOADER_ID_ENABLED_PRINT_SERVICES).forceLoad();

            updateOptionsUi();
            updateSummary();
        }

        private boolean capabilitiesChanged(PrinterCapabilitiesInfo oldCapabilities,
                PrinterCapabilitiesInfo newCapabilities) {
            if (oldCapabilities == null) {
                if (newCapabilities != null) {
                    return true;
                }
            } else if (!oldCapabilities.equals(newCapabilities)) {
                return true;
            }
            return false;
        }
    }

    private final class MyOnItemSelectedListener implements AdapterView.OnItemSelectedListener {
        @Override
        public void onItemSelected(AdapterView<?> spinner, View view, int position, long id) {
            boolean clearRanges = false;

            if (spinner == mDestinationSpinner) {
                if (position == AdapterView.INVALID_POSITION) {
                    return;
                }

                if (id == DEST_ADAPTER_ITEM_ID_MORE) {
                    startSelectPrinterActivity();
                    return;
                }

                PrinterHolder currentItem = (PrinterHolder) mDestinationSpinner.getSelectedItem();
                PrinterInfo currentPrinter = (currentItem != null) ? currentItem.printer : null;

                // Why on earth item selected is called if no selection changed.
                if (mCurrentPrinter == currentPrinter) {
                    return;
                }

                PrinterId oldId = null;
                if (mCurrentPrinter != null) {
                    oldId = mCurrentPrinter.getId();
                }

                mCurrentPrinter = currentPrinter;

                if (oldId != null) {
                    boolean printerRemoved = mDestinationSpinnerAdapter.pruneRemovedPrinter(oldId);

                    if (printerRemoved) {
                        // Trigger PrinterObserver.onChanged to adjust selection. This will call
                        // this function again.
                        mDestinationSpinnerAdapter.notifyDataSetChanged();
                        return;
                    }
                }

                PrinterHolder printerHolder = mDestinationSpinnerAdapter.getPrinterHolder(
                        currentPrinter.getId());
                if (!printerHolder.removed) {
                    setState(STATE_CONFIGURING);
                    ensurePreviewUiShown();
                }

                mPrintJob.setPrinterId(currentPrinter.getId());
                mPrintJob.setPrinterName(currentPrinter.getName());

                mPrinterRegistry.setTrackedPrinter(currentPrinter.getId());

                PrinterCapabilitiesInfo capabilities = currentPrinter.getCapabilities();
                if (capabilities != null) {
                    updatePrintAttributesFromCapabilities(capabilities);
                }

                mPrinterAvailabilityDetector.updatePrinter(currentPrinter);

                // Force a reload of the enabled print services to update
                // mAdvancedPrintOptionsActivity in onLoadFinished();
                getLoaderManager().getLoader(LOADER_ID_ENABLED_PRINT_SERVICES).forceLoad();
            } else if (spinner == mMediaSizeSpinner) {
                SpinnerItem<MediaSize> mediaItem = mMediaSizeSpinnerAdapter.getItem(position);
                PrintAttributes attributes = mPrintJob.getAttributes();

                MediaSize newMediaSize;
                if (mOrientationSpinner.getSelectedItemPosition() == 0) {
                    newMediaSize = mediaItem.value.asPortrait();
                } else {
                    newMediaSize = mediaItem.value.asLandscape();
                }

                if (newMediaSize != attributes.getMediaSize()) {
                    clearRanges = true;
                    attributes.setMediaSize(newMediaSize);
                }
            } else if (spinner == mColorModeSpinner) {
                SpinnerItem<Integer> colorModeItem = mColorModeSpinnerAdapter.getItem(position);
                mPrintJob.getAttributes().setColorMode(colorModeItem.value);
            } else if (spinner == mDuplexModeSpinner) {
                SpinnerItem<Integer> duplexModeItem = mDuplexModeSpinnerAdapter.getItem(position);
                mPrintJob.getAttributes().setDuplexMode(duplexModeItem.value);
            } else if (spinner == mOrientationSpinner) {
                SpinnerItem<Integer> orientationItem = mOrientationSpinnerAdapter.getItem(position);
                PrintAttributes attributes = mPrintJob.getAttributes();
                if (mMediaSizeSpinner.getSelectedItem() != null) {
                    boolean isPortrait = attributes.isPortrait();

                    if (isPortrait != (orientationItem.value == ORIENTATION_PORTRAIT)) {
                        clearRanges = true;
                        if (orientationItem.value == ORIENTATION_PORTRAIT) {
                            attributes.copyFrom(attributes.asPortrait());
                        } else {
                            attributes.copyFrom(attributes.asLandscape());
                        }
                    }
                }
            } else if (spinner == mRangeOptionsSpinner) {
                if (mRangeOptionsSpinner.getSelectedItemPosition() == 0) {
                    clearRanges = true;
                    mPageRangeEditText.setText("");
                } else if (TextUtils.isEmpty(mPageRangeEditText.getText())) {
                    mPageRangeEditText.setError("");
                }
            }

            if (clearRanges) {
                clearPageRanges();
            }

            updateOptionsUi();

            if (canUpdateDocument()) {
                updateDocument(false);
            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
            /* do nothing*/
        }
    }

    private final class SelectAllOnFocusListener implements OnFocusChangeListener {
        @Override
        public void onFocusChange(View view, boolean hasFocus) {
            EditText editText = (EditText) view;
            if (!TextUtils.isEmpty(editText.getText())) {
                editText.setSelection(editText.getText().length());
            }

            if (view == mPageRangeEditText && !hasFocus && mPageRangeEditText.getError() == null) {
                updateSelectedPagesFromTextField();
            }
        }
    }

    private final class RangeTextWatcher implements TextWatcher {
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            /* do nothing */
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            /* do nothing */
        }

        @Override
        public void afterTextChanged(Editable editable) {
            final boolean hadErrors = hasErrors();

            PrintDocumentInfo info = mPrintedDocument.getDocumentInfo().info;
            final int pageCount = (info != null) ? getAdjustedPageCount(info) : 0;
            PageRange[] ranges = PageRangeUtils.parsePageRanges(editable, pageCount);

            if (ranges.length == 0) {
                if (mPageRangeEditText.getError() == null) {
                    mPageRangeEditText.setError("");
                    updateOptionsUi();
                }
                return;
            }

            if (mPageRangeEditText.getError() != null) {
                mPageRangeEditText.setError(null);
                updateOptionsUi();
            }

            if (hadErrors && canUpdateDocument()) {
                updateDocument(false);
            }
        }
    }

    private final class EditTextWatcher implements TextWatcher {
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            /* do nothing */
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            /* do nothing */
        }

        @Override
        public void afterTextChanged(Editable editable) {
            final boolean hadErrors = hasErrors();

            if (editable.length() == 0) {
                if (mCopiesEditText.getError() == null) {
                    mCopiesEditText.setError("");
                    updateOptionsUi();
                }
                return;
            }

            int copies = 0;
            try {
                copies = Integer.parseInt(editable.toString());
            } catch (NumberFormatException nfe) {
                /* ignore */
            }

            if (copies < MIN_COPIES) {
                if (mCopiesEditText.getError() == null) {
                    mCopiesEditText.setError("");
                    updateOptionsUi();
                }
                return;
            }

            mPrintJob.setCopies(copies);

            if (mCopiesEditText.getError() != null) {
                mCopiesEditText.setError(null);
                updateOptionsUi();
            }

            if (hadErrors && canUpdateDocument()) {
                updateDocument(false);
            }
        }
    }

    private final class ProgressMessageController implements Runnable {
        private static final long PROGRESS_TIMEOUT_MILLIS = 1000;

        private final Handler mHandler;

        private boolean mPosted;

        /** State before run was executed */
        private int mPreviousState = -1;

        public ProgressMessageController(Context context) {
            mHandler = new Handler(context.getMainLooper(), null, false);
        }

        public void post() {
            if (mState == STATE_UPDATE_SLOW) {
                setState(STATE_UPDATE_SLOW);
                ensureProgressUiShown();
                updateOptionsUi();

                return;
            } else if (mPosted) {
                return;
            }
            mPreviousState = -1;
            mPosted = true;
            mHandler.postDelayed(this, PROGRESS_TIMEOUT_MILLIS);
        }

        private int getStateAfterCancel() {
            if (mPreviousState == -1) {
                return mState;
            } else {
                return mPreviousState;
            }
        }

        public int cancel() {
            int state;

            if (!mPosted) {
                state = getStateAfterCancel();
            } else {
                mPosted = false;
                mHandler.removeCallbacks(this);

                state = getStateAfterCancel();
            }

            mPreviousState = -1;

            return state;
        }

        @Override
        public void run() {
            mPosted = false;
            mPreviousState = mState;
            setState(STATE_UPDATE_SLOW);
            ensureProgressUiShown();
            updateOptionsUi();
        }
    }

    private static final class DocumentTransformer implements ServiceConnection {
        private static final String TEMP_FILE_PREFIX = "print_job";
        private static final String TEMP_FILE_EXTENSION = ".pdf";

        private final Context mContext;

        private final MutexFileProvider mFileProvider;

        private final PrintJobInfo mPrintJob;

        private final PageRange[] mPagesToShred;

        private final PrintAttributes mAttributesToApply;

        private final Runnable mCallback;

        public DocumentTransformer(Context context, PrintJobInfo printJob,
                MutexFileProvider fileProvider, PrintAttributes attributes,
                Runnable callback) {
            mContext = context;
            mPrintJob = printJob;
            mFileProvider = fileProvider;
            mCallback = callback;
            mPagesToShred = computePagesToShred(mPrintJob);
            mAttributesToApply = attributes;
        }

        public void transform() {
            // If we have only the pages we want, done.
            if (mPagesToShred.length <= 0 && mAttributesToApply == null) {
                mCallback.run();
                return;
            }

            // Bind to the manipulation service and the work
            // will be performed upon connection to the service.
            Intent intent = new Intent(PdfManipulationService.ACTION_GET_EDITOR);
            intent.setClass(mContext, PdfManipulationService.class);
            mContext.bindService(intent, this, Context.BIND_AUTO_CREATE);
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            final IPdfEditor editor = IPdfEditor.Stub.asInterface(service);
            new AsyncTask<Void, Void, Void>() {
                @Override
                protected Void doInBackground(Void... params) {
                    // It's OK to access the data members as they are
                    // final and this code is the last one to touch
                    // them as shredding is the very last step, so the
                    // UI is not interactive at this point.
                    doTransform(editor);
                    updatePrintJob();
                    return null;
                }

                @Override
                protected void onPostExecute(Void aVoid) {
                    mContext.unbindService(DocumentTransformer.this);
                    mCallback.run();
                }
            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            /* do nothing */
        }

        private void doTransform(IPdfEditor editor) {
            File tempFile = null;
            ParcelFileDescriptor src = null;
            ParcelFileDescriptor dst = null;
            InputStream in = null;
            OutputStream out = null;
            try {
                File jobFile = mFileProvider.acquireFile(null);
                src = ParcelFileDescriptor.open(jobFile, ParcelFileDescriptor.MODE_READ_WRITE);

                // Open the document.
                editor.openDocument(src);

                // We passed the fd over IPC, close this one.
                src.close();

                // Drop the pages.
                editor.removePages(mPagesToShred);

                // Apply print attributes if needed.
                if (mAttributesToApply != null) {
                    editor.applyPrintAttributes(mAttributesToApply);
                }

                // Write the modified PDF to a temp file.
                tempFile = File.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_EXTENSION,
                        mContext.getCacheDir());
                dst = ParcelFileDescriptor.open(tempFile, ParcelFileDescriptor.MODE_READ_WRITE);
                editor.write(dst);
                dst.close();

                // Close the document.
                editor.closeDocument();

                // Copy the temp file over the print job file.
                jobFile.delete();
                in = new FileInputStream(tempFile);
                out = new FileOutputStream(jobFile);
                Streams.copy(in, out);
            } catch (IOException|RemoteException e) {
                Log.e(LOG_TAG, "Error dropping pages", e);
            } finally {
                IoUtils.closeQuietly(src);
                IoUtils.closeQuietly(dst);
                IoUtils.closeQuietly(in);
                IoUtils.closeQuietly(out);
                if (tempFile != null) {
                    tempFile.delete();
                }
                mFileProvider.releaseFile();
            }
        }

        private void updatePrintJob() {
            // Update the print job pages.
            final int newPageCount = PageRangeUtils.getNormalizedPageCount(
                    mPrintJob.getPages(), 0);
            mPrintJob.setPages(new PageRange[]{PageRange.ALL_PAGES});

            // Update the print job document info.
            PrintDocumentInfo oldDocInfo = mPrintJob.getDocumentInfo();
            PrintDocumentInfo newDocInfo = new PrintDocumentInfo
                    .Builder(oldDocInfo.getName())
                    .setContentType(oldDocInfo.getContentType())
                    .setPageCount(newPageCount)
                    .build();

            File file = mFileProvider.acquireFile(null);
            try {
                newDocInfo.setDataSize(file.length());
            } finally {
                mFileProvider.releaseFile();
            }

            mPrintJob.setDocumentInfo(newDocInfo);
        }

        private static PageRange[] computePagesToShred(PrintJobInfo printJob) {
            List<PageRange> rangesToShred = new ArrayList<>();
            PageRange previousRange = null;

            PageRange[] printedPages = printJob.getPages();
            final int rangeCount = printedPages.length;
            for (int i = 0; i < rangeCount; i++) {
                PageRange range = printedPages[i];

                if (previousRange == null) {
                    final int startPageIdx = 0;
                    final int endPageIdx = range.getStart() - 1;
                    if (startPageIdx <= endPageIdx) {
                        PageRange removedRange = new PageRange(startPageIdx, endPageIdx);
                        rangesToShred.add(removedRange);
                    }
                } else {
                    final int startPageIdx = previousRange.getEnd() + 1;
                    final int endPageIdx = range.getStart() - 1;
                    if (startPageIdx <= endPageIdx) {
                        PageRange removedRange = new PageRange(startPageIdx, endPageIdx);
                        rangesToShred.add(removedRange);
                    }
                }

                if (i == rangeCount - 1) {
                    if (range.getEnd() != Integer.MAX_VALUE) {
                        rangesToShred.add(new PageRange(range.getEnd() + 1, Integer.MAX_VALUE));
                    }
                }

                previousRange = range;
            }

            PageRange[] result = new PageRange[rangesToShred.size()];
            rangesToShred.toArray(result);
            return result;
        }
    }
}
