/*
 * Copyright (C) 2013 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 android.print;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.Application.ActivityLifecycleCallbacks;
import android.content.ComponentName;
import android.content.Context;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.ICancellationSignal;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.print.PrintDocumentAdapter.LayoutResultCallback;
import android.print.PrintDocumentAdapter.WriteResultCallback;
import android.printservice.PrintServiceInfo;
import android.printservice.recommendation.IRecommendationsChangeListener;
import android.printservice.recommendation.RecommendationInfo;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;

import com.android.internal.os.SomeArgs;

import com.android.internal.util.Preconditions;
import libcore.io.IoUtils;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * System level service for accessing the printing capabilities of the platform.
 * <p>
 * To obtain a handle to the print manager do the following:
 * </p>
 *
 * <pre>
 * PrintManager printManager =
 *         (PrintManager) context.getSystemService(Context.PRINT_SERVICE);
 * </pre>
 *
 * <h3>Print mechanics</h3>
 * <p>
 * The key idea behind printing on the platform is that the content to be printed
 * should be laid out for the currently selected print options resulting in an
 * optimized output and higher user satisfaction. To achieve this goal the platform
 * declares a contract that the printing application has to follow which is defined
 * by the {@link PrintDocumentAdapter} class. At a higher level the contract is that
 * when the user selects some options from the print UI that may affect the way
 * content is laid out, for example page size, the application receives a callback
 * allowing it to layout the content to better fit these new constraints. After a
 * layout pass the system may ask the application to render one or more pages one
 * or more times. For example, an application may produce a single column list for
 * smaller page sizes and a multi-column table for larger page sizes.
 * </p>
 * <h3>Print jobs</h3>
 * <p>
 * Print jobs are started by calling the {@link #print(String, PrintDocumentAdapter,
 * PrintAttributes)} from an activity which results in bringing up the system print
 * UI. Once the print UI is up, when the user changes a selected print option that
 * affects the way content is laid out the system starts to interact with the
 * application following the mechanics described the section above.
 * </p>
 * <p>
 * Print jobs can be in {@link PrintJobInfo#STATE_CREATED created}, {@link
 * PrintJobInfo#STATE_QUEUED queued}, {@link PrintJobInfo#STATE_STARTED started},
 * {@link PrintJobInfo#STATE_BLOCKED blocked}, {@link PrintJobInfo#STATE_COMPLETED
 * completed}, {@link PrintJobInfo#STATE_FAILED failed}, and {@link
 * PrintJobInfo#STATE_CANCELED canceled} state. Print jobs are stored in dedicated
 * system spooler until they are handled which is they are cancelled or completed.
 * Active print jobs, ones that are not cancelled or completed, are considered failed
 * if the device reboots as the new boot may be after a very long time. The user may
 * choose to restart such print jobs. Once a print job is queued all relevant content
 * is stored in the system spooler and its lifecycle becomes detached from this of
 * the application that created it.
 * </p>
 * <p>
 * An applications can query the print spooler for current print jobs it created
 * but not print jobs created by other applications.
 * </p>
 *
 * @see PrintJob
 * @see PrintJobInfo
 */
public final class PrintManager {

    private static final String LOG_TAG = "PrintManager";

    private static final boolean DEBUG = false;

    private static final int MSG_NOTIFY_PRINT_JOB_STATE_CHANGED = 1;
    private static final int MSG_NOTIFY_PRINT_SERVICES_CHANGED = 2;
    private static final int MSG_NOTIFY_PRINT_SERVICE_RECOMMENDATIONS_CHANGED = 3;

    /**
     * Package name of print spooler.
     *
     * @hide
     */
    public static final String PRINT_SPOOLER_PACKAGE_NAME = "com.android.printspooler";

    /**
     * Select enabled services.
     * </p>
     * @see #getPrintServices
     * @hide
     */
    public static final int ENABLED_SERVICES = 1 << 0;

    /**
     * Select disabled services.
     * </p>
     * @see #getPrintServices
     * @hide
     */
    public static final int DISABLED_SERVICES = 1 << 1;

    /**
     * Select all services.
     * </p>
     * @see #getPrintServices
     * @hide
     */
    public static final int ALL_SERVICES = ENABLED_SERVICES | DISABLED_SERVICES;

    /**
     * The action for launching the print dialog activity.
     *
     * @hide
     */
    public static final String ACTION_PRINT_DIALOG = "android.print.PRINT_DIALOG";

    /**
     * Extra with the intent for starting the print dialog.
     * <p>
     * <strong>Type:</strong> {@link android.content.IntentSender}
     * </p>
     *
     * @hide
     */
    public static final String EXTRA_PRINT_DIALOG_INTENT =
            "android.print.intent.extra.EXTRA_PRINT_DIALOG_INTENT";

    /**
     * Extra with a print job.
     * <p>
     * <strong>Type:</strong> {@link android.print.PrintJobInfo}
     * </p>
     *
     * @hide
     */
    public static final String EXTRA_PRINT_JOB =
            "android.print.intent.extra.EXTRA_PRINT_JOB";

    /**
     * Extra with the print document adapter to be printed.
     * <p>
     * <strong>Type:</strong> {@link android.print.IPrintDocumentAdapter}
     * </p>
     *
     * @hide
     */
    public static final String EXTRA_PRINT_DOCUMENT_ADAPTER =
            "android.print.intent.extra.EXTRA_PRINT_DOCUMENT_ADAPTER";

    /** @hide */
    public static final int APP_ID_ANY = -2;

    private final Context mContext;

    private final IPrintManager mService;

    private final int mUserId;

    private final int mAppId;

    private final Handler mHandler;

    private Map<PrintJobStateChangeListener, PrintJobStateChangeListenerWrapper>
            mPrintJobStateChangeListeners;
    private Map<PrintServicesChangeListener, PrintServicesChangeListenerWrapper>
            mPrintServicesChangeListeners;
    private Map<PrintServiceRecommendationsChangeListener,
            PrintServiceRecommendationsChangeListenerWrapper>
            mPrintServiceRecommendationsChangeListeners;

    /** @hide */
    public interface PrintJobStateChangeListener {

        /**
         * Callback notifying that a print job state changed.
         *
         * @param printJobId The print job id.
         */
        public void onPrintJobStateChanged(PrintJobId printJobId);
    }

    /** @hide */
    public interface PrintServicesChangeListener {

        /**
         * Callback notifying that the print services changed.
         */
        public void onPrintServicesChanged();
    }

    /** @hide */
    public interface PrintServiceRecommendationsChangeListener {

        /**
         * Callback notifying that the print service recommendations changed.
         */
        void onPrintServiceRecommendationsChanged();
    }

    /**
     * Creates a new instance.
     *
     * @param context The current context in which to operate.
     * @param service The backing system service.
     * @param userId The user id in which to operate.
     * @param appId The application id in which to operate.
     * @hide
     */
    public PrintManager(Context context, IPrintManager service, int userId, int appId) {
        mContext = context;
        mService = service;
        mUserId = userId;
        mAppId = appId;
        mHandler = new Handler(context.getMainLooper(), null, false) {
            @Override
            public void handleMessage(Message message) {
                switch (message.what) {
                    case MSG_NOTIFY_PRINT_JOB_STATE_CHANGED: {
                        SomeArgs args = (SomeArgs) message.obj;
                        PrintJobStateChangeListenerWrapper wrapper =
                                (PrintJobStateChangeListenerWrapper) args.arg1;
                        PrintJobStateChangeListener listener = wrapper.getListener();
                        if (listener != null) {
                            PrintJobId printJobId = (PrintJobId) args.arg2;
                            listener.onPrintJobStateChanged(printJobId);
                        }
                        args.recycle();
                    } break;
                    case MSG_NOTIFY_PRINT_SERVICES_CHANGED: {
                        PrintServicesChangeListenerWrapper wrapper =
                                (PrintServicesChangeListenerWrapper) message.obj;
                        PrintServicesChangeListener listener = wrapper.getListener();
                        if (listener != null) {
                            listener.onPrintServicesChanged();
                        }
                    } break;
                    case MSG_NOTIFY_PRINT_SERVICE_RECOMMENDATIONS_CHANGED: {
                        PrintServiceRecommendationsChangeListenerWrapper wrapper =
                                (PrintServiceRecommendationsChangeListenerWrapper) message.obj;
                        PrintServiceRecommendationsChangeListener listener = wrapper.getListener();
                        if (listener != null) {
                            listener.onPrintServiceRecommendationsChanged();
                        }
                    } break;
                }
            }
        };
    }

    /**
     * Creates an instance that can access all print jobs.
     *
     * @param userId The user id for which to get all print jobs.
     * @return An instance if the caller has the permission to access all print
     *         jobs, null otherwise.
     * @hide
     */
    public PrintManager getGlobalPrintManagerForUser(int userId) {
        if (mService == null) {
            Log.w(LOG_TAG, "Feature android.software.print not available");
            return null;
        }
        return new PrintManager(mContext, mService, userId, APP_ID_ANY);
    }

    PrintJobInfo getPrintJobInfo(PrintJobId printJobId) {
        try {
            return mService.getPrintJobInfo(printJobId, mAppId, mUserId);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Adds a listener for observing the state of print jobs.
     *
     * @param listener The listener to add.
     * @hide
     */
    public void addPrintJobStateChangeListener(PrintJobStateChangeListener listener) {
        if (mService == null) {
            Log.w(LOG_TAG, "Feature android.software.print not available");
            return;
        }
        if (mPrintJobStateChangeListeners == null) {
            mPrintJobStateChangeListeners = new ArrayMap<PrintJobStateChangeListener,
                    PrintJobStateChangeListenerWrapper>();
        }
        PrintJobStateChangeListenerWrapper wrappedListener =
                new PrintJobStateChangeListenerWrapper(listener, mHandler);
        try {
            mService.addPrintJobStateChangeListener(wrappedListener, mAppId, mUserId);
            mPrintJobStateChangeListeners.put(listener, wrappedListener);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Removes a listener for observing the state of print jobs.
     *
     * @param listener The listener to remove.
     * @hide
     */
    public void removePrintJobStateChangeListener(PrintJobStateChangeListener listener) {
        if (mService == null) {
            Log.w(LOG_TAG, "Feature android.software.print not available");
            return;
        }
        if (mPrintJobStateChangeListeners == null) {
            return;
        }
        PrintJobStateChangeListenerWrapper wrappedListener =
                mPrintJobStateChangeListeners.remove(listener);
        if (wrappedListener == null) {
            return;
        }
        if (mPrintJobStateChangeListeners.isEmpty()) {
            mPrintJobStateChangeListeners = null;
        }
        wrappedListener.destroy();
        try {
            mService.removePrintJobStateChangeListener(wrappedListener, mUserId);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Gets a print job given its id.
     *
     * @param printJobId The id of the print job.
     * @return The print job list.
     * @see PrintJob
     * @hide
     */
    public PrintJob getPrintJob(PrintJobId printJobId) {
        if (mService == null) {
            Log.w(LOG_TAG, "Feature android.software.print not available");
            return null;
        }
        try {
            PrintJobInfo printJob = mService.getPrintJobInfo(printJobId, mAppId, mUserId);
            if (printJob != null) {
                return new PrintJob(printJob, this);
            }
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
        return null;
    }

    /**
     * Get the custom icon for a printer. If the icon is not cached, the icon is
     * requested asynchronously. Once it is available the printer is updated.
     *
     * @param printerId the id of the printer the icon should be loaded for
     * @return the custom icon to be used for the printer or null if the icon is
     *         not yet available
     * @see android.print.PrinterInfo.Builder#setHasCustomPrinterIcon()
     * @hide
     */
    public Icon getCustomPrinterIcon(PrinterId printerId) {
        if (mService == null) {
            Log.w(LOG_TAG, "Feature android.software.print not available");
            return null;
        }
        try {
            return mService.getCustomPrinterIcon(printerId, mUserId);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Gets the print jobs for this application.
     *
     * @return The print job list.
     * @see PrintJob
     */
    public @NonNull List<PrintJob> getPrintJobs() {
        if (mService == null) {
            Log.w(LOG_TAG, "Feature android.software.print not available");
            return Collections.emptyList();
        }
        try {
            List<PrintJobInfo> printJobInfos = mService.getPrintJobInfos(mAppId, mUserId);
            if (printJobInfos == null) {
                return Collections.emptyList();
            }
            final int printJobCount = printJobInfos.size();
            List<PrintJob> printJobs = new ArrayList<PrintJob>(printJobCount);
            for (int i = 0; i < printJobCount; i++) {
                printJobs.add(new PrintJob(printJobInfos.get(i), this));
            }
            return printJobs;
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    void cancelPrintJob(PrintJobId printJobId) {
        if (mService == null) {
            Log.w(LOG_TAG, "Feature android.software.print not available");
            return;
        }
        try {
            mService.cancelPrintJob(printJobId, mAppId, mUserId);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    void restartPrintJob(PrintJobId printJobId) {
        if (mService == null) {
            Log.w(LOG_TAG, "Feature android.software.print not available");
            return;
        }
        try {
            mService.restartPrintJob(printJobId, mAppId, mUserId);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Creates a print job for printing a {@link PrintDocumentAdapter} with
     * default print attributes.
     * <p>
     * Calling this method brings the print UI allowing the user to customize
     * the print job and returns a {@link PrintJob} object without waiting for the
     * user to customize or confirm the print job. The returned print job instance
     * is in a {@link PrintJobInfo#STATE_CREATED created} state.
     * <p>
     * This method can be called only from an {@link Activity}. The rationale is that
     * printing from a service will create an inconsistent user experience as the print
     * UI would appear without any context.
     * </p>
     * <p>
     * Also the passed in {@link PrintDocumentAdapter} will be considered invalid if
     * your activity is finished. The rationale is that once the activity that
     * initiated printing is finished, the provided adapter may be in an inconsistent
     * state as it may depend on the UI presented by the activity.
     * </p>
     * <p>
     * The default print attributes are a hint to the system how the data is to
     * be printed. For example, a photo editor may look at the photo aspect ratio
     * to determine the default orientation and provide a hint whether the printing
     * should be in portrait or landscape. The system will do a best effort to
     * selected the hinted options in the print dialog, given the current printer
     * supports them.
     * </p>
     * <p>
     * <strong>Note:</strong> Calling this method will bring the print dialog and
     * the system will connect to the provided {@link PrintDocumentAdapter}. If a
     * configuration change occurs that you application does not handle, for example
     * a rotation change, the system will drop the connection to the adapter as the
     * activity has to be recreated and the old adapter may be invalid in this context,
     * hence a new adapter instance is required. As a consequence, if your activity
     * does not handle configuration changes (default behavior), you have to save the
     * state that you were printing and call this method again when your activity
     * is recreated.
     * </p>
     *
     * @param printJobName A name for the new print job which is shown to the user.
     * @param documentAdapter An adapter that emits the document to print.
     * @param attributes The default print job attributes or <code>null</code>.
     * @return The created print job on success or null on failure.
     * @throws IllegalStateException If not called from an {@link Activity}.
     * @throws IllegalArgumentException If the print job name is empty or the
     * document adapter is null.
     *
     * @see PrintJob
     */
    public @NonNull PrintJob print(@NonNull String printJobName,
            @NonNull PrintDocumentAdapter documentAdapter,
            @Nullable PrintAttributes attributes) {
        if (mService == null) {
            Log.w(LOG_TAG, "Feature android.software.print not available");
            return null;
        }
        if (!(mContext instanceof Activity)) {
            throw new IllegalStateException("Can print only from an activity");
        }
        if (TextUtils.isEmpty(printJobName)) {
            throw new IllegalArgumentException("printJobName cannot be empty");
        }
        if (documentAdapter == null) {
            throw new IllegalArgumentException("documentAdapter cannot be null");
        }
        PrintDocumentAdapterDelegate delegate = new PrintDocumentAdapterDelegate(
                (Activity) mContext, documentAdapter);
        try {
            Bundle result = mService.print(printJobName, delegate,
                    attributes, mContext.getPackageName(), mAppId, mUserId);
            if (result != null) {
                PrintJobInfo printJob = result.getParcelable(EXTRA_PRINT_JOB);
                IntentSender intent = result.getParcelable(EXTRA_PRINT_DIALOG_INTENT);
                if (printJob == null || intent == null) {
                    return null;
                }
                try {
                    mContext.startIntentSender(intent, null, 0, 0, 0);
                    return new PrintJob(printJob, this);
                } catch (SendIntentException sie) {
                    Log.e(LOG_TAG, "Couldn't start print job config activity.", sie);
                }
            }
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
        return null;
    }

    /**
     * Listen for changes to the installed and enabled print services.
     *
     * @param listener the listener to add
     *
     * @see android.print.PrintManager#getPrintServices
     */
    void addPrintServicesChangeListener(@NonNull PrintServicesChangeListener listener) {
        Preconditions.checkNotNull(listener);

        if (mService == null) {
            Log.w(LOG_TAG, "Feature android.software.print not available");
            return;
        }
        if (mPrintServicesChangeListeners == null) {
            mPrintServicesChangeListeners = new ArrayMap<>();
        }
        PrintServicesChangeListenerWrapper wrappedListener =
                new PrintServicesChangeListenerWrapper(listener, mHandler);
        try {
            mService.addPrintServicesChangeListener(wrappedListener, mUserId);
            mPrintServicesChangeListeners.put(listener, wrappedListener);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Stop listening for changes to the installed and enabled print services.
     *
     * @param listener the listener to remove
     *
     * @see android.print.PrintManager#getPrintServices
     */
    void removePrintServicesChangeListener(@NonNull PrintServicesChangeListener listener) {
        Preconditions.checkNotNull(listener);

        if (mService == null) {
            Log.w(LOG_TAG, "Feature android.software.print not available");
            return;
        }
        if (mPrintServicesChangeListeners == null) {
            return;
        }
        PrintServicesChangeListenerWrapper wrappedListener =
                mPrintServicesChangeListeners.remove(listener);
        if (wrappedListener == null) {
            return;
        }
        if (mPrintServicesChangeListeners.isEmpty()) {
            mPrintServicesChangeListeners = null;
        }
        wrappedListener.destroy();
        try {
            mService.removePrintServicesChangeListener(wrappedListener, mUserId);
        } catch (RemoteException re) {
            Log.e(LOG_TAG, "Error removing print services change listener", re);
        }
    }

    /**
     * Gets the list of print services, but does not register for updates. The user has to register
     * for updates by itself, or use {@link PrintServicesLoader}.
     *
     * @param selectionFlags flags selecting which services to get. Either
     *                       {@link #ENABLED_SERVICES},{@link #DISABLED_SERVICES}, or both.
     *
     * @return The print service list or an empty list.
     *
     * @see #addPrintServicesChangeListener(PrintServicesChangeListener)
     * @see #removePrintServicesChangeListener(PrintServicesChangeListener)
     *
     * @hide
     */
    public @NonNull List<PrintServiceInfo> getPrintServices(int selectionFlags) {
        Preconditions.checkFlagsArgument(selectionFlags, ALL_SERVICES);

        try {
            List<PrintServiceInfo> services = mService.getPrintServices(selectionFlags, mUserId);
            if (services != null) {
                return services;
            }
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
        return Collections.emptyList();
    }

    /**
     * Listen for changes to the print service recommendations.
     *
     * @param listener the listener to add
     *
     * @see android.print.PrintManager#getPrintServiceRecommendations
     */
    void addPrintServiceRecommendationsChangeListener(
            @NonNull PrintServiceRecommendationsChangeListener listener) {
        Preconditions.checkNotNull(listener);

        if (mService == null) {
            Log.w(LOG_TAG, "Feature android.software.print not available");
            return;
        }
        if (mPrintServiceRecommendationsChangeListeners == null) {
            mPrintServiceRecommendationsChangeListeners = new ArrayMap<>();
        }
        PrintServiceRecommendationsChangeListenerWrapper wrappedListener =
                new PrintServiceRecommendationsChangeListenerWrapper(listener, mHandler);
        try {
            mService.addPrintServiceRecommendationsChangeListener(wrappedListener, mUserId);
            mPrintServiceRecommendationsChangeListeners.put(listener, wrappedListener);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Stop listening for changes to the print service recommendations.
     *
     * @param listener the listener to remove
     *
     * @see android.print.PrintManager#getPrintServiceRecommendations
     */
    void removePrintServiceRecommendationsChangeListener(
            @NonNull PrintServiceRecommendationsChangeListener listener) {
        Preconditions.checkNotNull(listener);

        if (mService == null) {
            Log.w(LOG_TAG, "Feature android.software.print not available");
            return;
        }
        if (mPrintServiceRecommendationsChangeListeners == null) {
            return;
        }
        PrintServiceRecommendationsChangeListenerWrapper wrappedListener =
                mPrintServiceRecommendationsChangeListeners.remove(listener);
        if (wrappedListener == null) {
            return;
        }
        if (mPrintServiceRecommendationsChangeListeners.isEmpty()) {
            mPrintServiceRecommendationsChangeListeners = null;
        }
        wrappedListener.destroy();
        try {
            mService.removePrintServiceRecommendationsChangeListener(wrappedListener, mUserId);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Gets the list of print service recommendations, but does not register for updates. The user
     * has to register for updates by itself, or use {@link PrintServiceRecommendationsLoader}.
     *
     * @return The print service recommendations list or an empty list.
     *
     * @see #addPrintServiceRecommendationsChangeListener
     * @see #removePrintServiceRecommendationsChangeListener
     *
     * @hide
     */
    public @NonNull List<RecommendationInfo> getPrintServiceRecommendations() {
        try {
            List<RecommendationInfo> recommendations =
                    mService.getPrintServiceRecommendations(mUserId);
            if (recommendations != null) {
                return recommendations;
            }
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
        return Collections.emptyList();
    }

    /**
     * @hide
     */
    public PrinterDiscoverySession createPrinterDiscoverySession() {
        if (mService == null) {
            Log.w(LOG_TAG, "Feature android.software.print not available");
            return null;
        }
        return new PrinterDiscoverySession(mService, mContext, mUserId);
    }

    /**
     * Enable or disable a print service.
     *
     * @param service The service to enabled or disable
     * @param isEnabled whether the service should be enabled or disabled
     *
     * @hide
     */
    public void setPrintServiceEnabled(@NonNull ComponentName service, boolean isEnabled) {
        if (mService == null) {
            Log.w(LOG_TAG, "Feature android.software.print not available");
            return;
        }
        try {
            mService.setPrintServiceEnabled(service, isEnabled, mUserId);
        } catch (RemoteException re) {
            Log.e(LOG_TAG, "Error enabling or disabling " + service, re);
        }
    }

    /**
     * @hide
     */
    public static final class PrintDocumentAdapterDelegate extends IPrintDocumentAdapter.Stub
            implements ActivityLifecycleCallbacks {
        private final Object mLock = new Object();

        private Activity mActivity; // Strong reference OK - cleared in destroy

        private PrintDocumentAdapter mDocumentAdapter; // Strong reference OK - cleared in destroy

        private Handler mHandler; // Strong reference OK - cleared in destroy

        private IPrintDocumentAdapterObserver mObserver; // Strong reference OK - cleared in destroy

        private DestroyableCallback mPendingCallback;

        public PrintDocumentAdapterDelegate(Activity activity,
                PrintDocumentAdapter documentAdapter) {
            mActivity = activity;
            mDocumentAdapter = documentAdapter;
            mHandler = new MyHandler(mActivity.getMainLooper());
            mActivity.getApplication().registerActivityLifecycleCallbacks(this);
        }

        @Override
        public void setObserver(IPrintDocumentAdapterObserver observer) {
            final boolean destroyed;
            synchronized (mLock) {
                mObserver = observer;
                destroyed = isDestroyedLocked();
            }

            if (destroyed && observer != null) {
                try {
                    observer.onDestroy();
                } catch (RemoteException re) {
                    Log.e(LOG_TAG, "Error announcing destroyed state", re);
                }
            }
        }

        @Override
        public void start() {
            synchronized (mLock) {
                // If destroyed the handler is null.
                if (!isDestroyedLocked()) {
                    mHandler.obtainMessage(MyHandler.MSG_ON_START,
                            mDocumentAdapter).sendToTarget();
                }
            }
        }

        @Override
        public void layout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
                ILayoutResultCallback callback, Bundle metadata, int sequence) {

            ICancellationSignal cancellationTransport = CancellationSignal.createTransport();
            try {
                callback.onLayoutStarted(cancellationTransport, sequence);
            } catch (RemoteException re) {
                // The spooler is dead - can't recover.
                Log.e(LOG_TAG, "Error notifying for layout start", re);
                return;
            }

            synchronized (mLock) {
                // If destroyed the handler is null.
                if (isDestroyedLocked()) {
                    return;
                }

                CancellationSignal cancellationSignal = CancellationSignal.fromTransport(
                        cancellationTransport);

                SomeArgs args = SomeArgs.obtain();
                args.arg1 = mDocumentAdapter;
                args.arg2 = oldAttributes;
                args.arg3 = newAttributes;
                args.arg4 = cancellationSignal;
                args.arg5 = new MyLayoutResultCallback(callback, sequence);
                args.arg6 = metadata;

                mHandler.obtainMessage(MyHandler.MSG_ON_LAYOUT, args).sendToTarget();
            }
        }

        @Override
        public void write(PageRange[] pages, ParcelFileDescriptor fd,
                IWriteResultCallback callback, int sequence) {

            ICancellationSignal cancellationTransport = CancellationSignal.createTransport();
            try {
                callback.onWriteStarted(cancellationTransport, sequence);
            } catch (RemoteException re) {
                // The spooler is dead - can't recover.
                Log.e(LOG_TAG, "Error notifying for write start", re);
                return;
            }

            synchronized (mLock) {
                // If destroyed the handler is null.
                if (isDestroyedLocked()) {
                    return;
                }

                CancellationSignal cancellationSignal = CancellationSignal.fromTransport(
                        cancellationTransport);

                SomeArgs args = SomeArgs.obtain();
                args.arg1 = mDocumentAdapter;
                args.arg2 = pages;
                args.arg3 = fd;
                args.arg4 = cancellationSignal;
                args.arg5 = new MyWriteResultCallback(callback, fd, sequence);

                mHandler.obtainMessage(MyHandler.MSG_ON_WRITE, args).sendToTarget();
            }
        }

        @Override
        public void finish() {
            synchronized (mLock) {
                // If destroyed the handler is null.
                if (!isDestroyedLocked()) {
                    mHandler.obtainMessage(MyHandler.MSG_ON_FINISH,
                            mDocumentAdapter).sendToTarget();
                }
            }
        }

        @Override
        public void kill(String reason) {
            synchronized (mLock) {
                // If destroyed the handler is null.
                if (!isDestroyedLocked()) {
                    mHandler.obtainMessage(MyHandler.MSG_ON_KILL,
                            reason).sendToTarget();
                }
            }
        }

        @Override
        public void onActivityPaused(Activity activity) {
            /* do nothing */
        }

        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            /* do nothing */
        }

        @Override
        public void onActivityStarted(Activity activity) {
            /* do nothing */
        }

        @Override
        public void onActivityResumed(Activity activity) {
            /* do nothing */
        }

        @Override
        public void onActivityStopped(Activity activity) {
            /* do nothing */
        }

        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
            /* do nothing */
        }

        @Override
        public void onActivityDestroyed(Activity activity) {
            // We really care only if the activity is being destroyed to
            // notify the the print spooler so it can close the print dialog.
            // Note the the spooler has a death recipient that observes if
            // this process gets killed so we cover the case of onDestroy not
            // being called due to this process being killed to reclaim memory.
            IPrintDocumentAdapterObserver observer = null;
            synchronized (mLock) {
                if (activity == mActivity) {
                    observer = mObserver;
                    destroyLocked();
                }
            }
            if (observer != null) {
                try {
                    observer.onDestroy();
                } catch (RemoteException re) {
                    Log.e(LOG_TAG, "Error announcing destroyed state", re);
                }
            }
        }

        private boolean isDestroyedLocked() {
            return (mActivity == null);
        }

        private void destroyLocked() {
            mActivity.getApplication().unregisterActivityLifecycleCallbacks(
                    PrintDocumentAdapterDelegate.this);
            mActivity = null;

            mDocumentAdapter = null;

            // This method is only called from the main thread, so
            // clearing the messages guarantees that any time a
            // message is handled we are not in a destroyed state.
            mHandler.removeMessages(MyHandler.MSG_ON_START);
            mHandler.removeMessages(MyHandler.MSG_ON_LAYOUT);
            mHandler.removeMessages(MyHandler.MSG_ON_WRITE);
            mHandler.removeMessages(MyHandler.MSG_ON_FINISH);
            mHandler = null;

            mObserver = null;

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

        private final class MyHandler extends Handler {
            public static final int MSG_ON_START = 1;
            public static final int MSG_ON_LAYOUT = 2;
            public static final int MSG_ON_WRITE = 3;
            public static final int MSG_ON_FINISH = 4;
            public static final int MSG_ON_KILL = 5;

            public MyHandler(Looper looper) {
                super(looper, null, true);
            }

            @Override
            public void handleMessage(Message message) {
                switch (message.what) {
                    case MSG_ON_START: {
                        if (DEBUG) {
                            Log.i(LOG_TAG, "onStart()");
                        }

                        ((PrintDocumentAdapter) message.obj).onStart();
                    } break;

                    case MSG_ON_LAYOUT: {
                        SomeArgs args = (SomeArgs) message.obj;
                        PrintDocumentAdapter adapter = (PrintDocumentAdapter) args.arg1;
                        PrintAttributes oldAttributes = (PrintAttributes) args.arg2;
                        PrintAttributes newAttributes = (PrintAttributes) args.arg3;
                        CancellationSignal cancellation = (CancellationSignal) args.arg4;
                        LayoutResultCallback callback = (LayoutResultCallback) args.arg5;
                        Bundle metadata = (Bundle) args.arg6;
                        args.recycle();

                        if (DEBUG) {
                            StringBuilder builder = new StringBuilder();
                            builder.append("PrintDocumentAdapter#onLayout() {\n");
                            builder.append("\n  oldAttributes:").append(oldAttributes);
                            builder.append("\n  newAttributes:").append(newAttributes);
                            builder.append("\n  preview:").append(metadata.getBoolean(
                                    PrintDocumentAdapter.EXTRA_PRINT_PREVIEW));
                            builder.append("\n}");
                            Log.i(LOG_TAG, builder.toString());
                        }

                        adapter.onLayout(oldAttributes, newAttributes, cancellation,
                                callback, metadata);
                    } break;

                    case MSG_ON_WRITE: {
                        SomeArgs args = (SomeArgs) message.obj;
                        PrintDocumentAdapter adapter = (PrintDocumentAdapter) args.arg1;
                        PageRange[] pages = (PageRange[]) args.arg2;
                        ParcelFileDescriptor fd = (ParcelFileDescriptor) args.arg3;
                        CancellationSignal cancellation = (CancellationSignal) args.arg4;
                        WriteResultCallback callback = (WriteResultCallback) args.arg5;
                        args.recycle();

                        if (DEBUG) {
                            StringBuilder builder = new StringBuilder();
                            builder.append("PrintDocumentAdapter#onWrite() {\n");
                            builder.append("\n  pages:").append(Arrays.toString(pages));
                            builder.append("\n}");
                            Log.i(LOG_TAG, builder.toString());
                        }

                        adapter.onWrite(pages, fd, cancellation, callback);
                    } break;

                    case MSG_ON_FINISH: {
                        if (DEBUG) {
                            Log.i(LOG_TAG, "onFinish()");
                        }

                        ((PrintDocumentAdapter) message.obj).onFinish();

                        // Done printing, so destroy this instance as it
                        // should not be used anymore.
                        synchronized (mLock) {
                            destroyLocked();
                        }
                    } break;

                    case MSG_ON_KILL: {
                        if (DEBUG) {
                            Log.i(LOG_TAG, "onKill()");
                        }

                        String reason = (String) message.obj;
                        throw new RuntimeException(reason);
                    }

                    default: {
                        throw new IllegalArgumentException("Unknown message: "
                                + message.what);
                    }
                }
            }
        }

        private interface DestroyableCallback {
            public void destroy();
        }

        private final class MyLayoutResultCallback extends LayoutResultCallback
                implements DestroyableCallback {
            private ILayoutResultCallback mCallback;
            private final int mSequence;

            public MyLayoutResultCallback(ILayoutResultCallback callback,
                    int sequence) {
                mCallback = callback;
                mSequence = sequence;
            }

            @Override
            public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
                final ILayoutResultCallback callback;
                synchronized (mLock) {
                    callback = mCallback;
                }

                // If the callback is null we are destroyed.
                if (callback == null) {
                    Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you "
                            + "finish the printing activity before print completion "
                            + "or did you invoke a callback after finish?");
                    return;
                }

                try {
                    if (info == null) {
                        throw new NullPointerException("document info cannot be null");
                    }

                    try {
                        callback.onLayoutFinished(info, changed, mSequence);
                    } catch (RemoteException re) {
                        Log.e(LOG_TAG, "Error calling onLayoutFinished", re);
                    }
                } finally {
                    destroy();
                }
            }

            @Override
            public void onLayoutFailed(CharSequence error) {
                final ILayoutResultCallback callback;
                synchronized (mLock) {
                    callback = mCallback;
                }

                // If the callback is null we are destroyed.
                if (callback == null) {
                    Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you "
                            + "finish the printing activity before print completion "
                            + "or did you invoke a callback after finish?");
                    return;
                }

                try {
                    callback.onLayoutFailed(error, mSequence);
                } catch (RemoteException re) {
                    Log.e(LOG_TAG, "Error calling onLayoutFailed", re);
                } finally {
                    destroy();
                }
            }

            @Override
            public void onLayoutCancelled() {
                final ILayoutResultCallback callback;
                synchronized (mLock) {
                    callback = mCallback;
                }

                // If the callback is null we are destroyed.
                if (callback == null) {
                    Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you "
                            + "finish the printing activity before print completion "
                            + "or did you invoke a callback after finish?");
                    return;
                }

                try {
                    callback.onLayoutCanceled(mSequence);
                } catch (RemoteException re) {
                    Log.e(LOG_TAG, "Error calling onLayoutFailed", re);
                } finally {
                    destroy();
                }
            }

            @Override
            public void destroy() {
                synchronized (mLock) {
                    mCallback = null;
                    mPendingCallback = null;
                }
            }
        }

        private final class MyWriteResultCallback extends WriteResultCallback
                implements DestroyableCallback {
            private ParcelFileDescriptor mFd;
            private IWriteResultCallback mCallback;
            private final int mSequence;

            public MyWriteResultCallback(IWriteResultCallback callback,
                    ParcelFileDescriptor fd, int sequence) {
                mFd = fd;
                mSequence = sequence;
                mCallback = callback;
            }

            @Override
            public void onWriteFinished(PageRange[] pages) {
                final IWriteResultCallback callback;
                synchronized (mLock) {
                    callback = mCallback;
                }

                // If the callback is null we are destroyed.
                if (callback == null) {
                    Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you "
                            + "finish the printing activity before print completion "
                            + "or did you invoke a callback after finish?");
                    return;
                }

                try {
                    if (pages == null) {
                        throw new IllegalArgumentException("pages cannot be null");
                    }
                    if (pages.length == 0) {
                        throw new IllegalArgumentException("pages cannot be empty");
                    }

                    try {
                        callback.onWriteFinished(pages, mSequence);
                    } catch (RemoteException re) {
                        Log.e(LOG_TAG, "Error calling onWriteFinished", re);
                    }
                } finally {
                    destroy();
                }
            }

            @Override
            public void onWriteFailed(CharSequence error) {
                final IWriteResultCallback callback;
                synchronized (mLock) {
                    callback = mCallback;
                }

                // If the callback is null we are destroyed.
                if (callback == null) {
                    Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you "
                            + "finish the printing activity before print completion "
                            + "or did you invoke a callback after finish?");
                    return;
                }

                try {
                    callback.onWriteFailed(error, mSequence);
                } catch (RemoteException re) {
                    Log.e(LOG_TAG, "Error calling onWriteFailed", re);
                } finally {
                    destroy();
                }
            }

            @Override
            public void onWriteCancelled() {
                final IWriteResultCallback callback;
                synchronized (mLock) {
                    callback = mCallback;
                }

                // If the callback is null we are destroyed.
                if (callback == null) {
                    Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you "
                            + "finish the printing activity before print completion "
                            + "or did you invoke a callback after finish?");
                    return;
                }

                try {
                    callback.onWriteCanceled(mSequence);
                } catch (RemoteException re) {
                    Log.e(LOG_TAG, "Error calling onWriteCanceled", re);
                } finally {
                    destroy();
                }
            }

            @Override
            public void destroy() {
                synchronized (mLock) {
                    IoUtils.closeQuietly(mFd);
                    mCallback = null;
                    mFd = null;
                    mPendingCallback = null;
                }
            }
        }
    }

    /**
     * @hide
     */
    public static final class PrintJobStateChangeListenerWrapper extends
            IPrintJobStateChangeListener.Stub {
        private final WeakReference<PrintJobStateChangeListener> mWeakListener;
        private final WeakReference<Handler> mWeakHandler;

        public PrintJobStateChangeListenerWrapper(PrintJobStateChangeListener listener,
                Handler handler) {
            mWeakListener = new WeakReference<PrintJobStateChangeListener>(listener);
            mWeakHandler = new WeakReference<Handler>(handler);
        }

        @Override
        public void onPrintJobStateChanged(PrintJobId printJobId) {
            Handler handler = mWeakHandler.get();
            PrintJobStateChangeListener listener = mWeakListener.get();
            if (handler != null && listener != null) {
                SomeArgs args = SomeArgs.obtain();
                args.arg1 = this;
                args.arg2 = printJobId;
                handler.obtainMessage(MSG_NOTIFY_PRINT_JOB_STATE_CHANGED,
                        args).sendToTarget();
            }
        }

        public void destroy() {
            mWeakListener.clear();
        }

        public PrintJobStateChangeListener getListener() {
            return mWeakListener.get();
        }
    }

    /**
     * @hide
     */
    public static final class PrintServicesChangeListenerWrapper extends
            IPrintServicesChangeListener.Stub {
        private final WeakReference<PrintServicesChangeListener> mWeakListener;
        private final WeakReference<Handler> mWeakHandler;

        public PrintServicesChangeListenerWrapper(PrintServicesChangeListener listener,
                Handler handler) {
            mWeakListener = new WeakReference<>(listener);
            mWeakHandler = new WeakReference<>(handler);
        }

        @Override
        public void onPrintServicesChanged() {
            Handler handler = mWeakHandler.get();
            PrintServicesChangeListener listener = mWeakListener.get();
            if (handler != null && listener != null) {
                handler.obtainMessage(MSG_NOTIFY_PRINT_SERVICES_CHANGED, this).sendToTarget();
            }
        }

        public void destroy() {
            mWeakListener.clear();
        }

        public PrintServicesChangeListener getListener() {
            return mWeakListener.get();
        }
    }

    /**
     * @hide
     */
    public static final class PrintServiceRecommendationsChangeListenerWrapper extends
            IRecommendationsChangeListener.Stub {
        private final WeakReference<PrintServiceRecommendationsChangeListener> mWeakListener;
        private final WeakReference<Handler> mWeakHandler;

        public PrintServiceRecommendationsChangeListenerWrapper(
                PrintServiceRecommendationsChangeListener listener, Handler handler) {
            mWeakListener = new WeakReference<>(listener);
            mWeakHandler = new WeakReference<>(handler);
        }

        @Override
        public void onRecommendationsChanged() {
            Handler handler = mWeakHandler.get();
            PrintServiceRecommendationsChangeListener listener = mWeakListener.get();
            if (handler != null && listener != null) {
                handler.obtainMessage(MSG_NOTIFY_PRINT_SERVICE_RECOMMENDATIONS_CHANGED,
                        this).sendToTarget();
            }
        }

        public void destroy() {
            mWeakListener.clear();
        }

        public PrintServiceRecommendationsChangeListener getListener() {
            return mWeakListener.get();
        }
    }
}
