/*
 * 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 com.android.server.print;

import static android.content.pm.PackageManager.GET_META_DATA;
import static android.content.pm.PackageManager.GET_SERVICES;
import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
import android.os.IInterface;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.UserHandle;
import android.print.IPrintDocumentAdapter;
import android.print.IPrintJobStateChangeListener;
import android.printservice.recommendation.IRecommendationsChangeListener;
import android.print.IPrintServicesChangeListener;
import android.print.IPrinterDiscoveryObserver;
import android.print.PrintAttributes;
import android.print.PrintJobId;
import android.print.PrintJobInfo;
import android.print.PrintManager;
import android.printservice.recommendation.RecommendationInfo;
import android.print.PrinterId;
import android.print.PrinterInfo;
import android.printservice.PrintServiceInfo;
import android.provider.DocumentsContract;
import android.provider.Settings;
import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.R;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.SomeArgs;
import com.android.server.print.RemotePrintService.PrintServiceCallbacks;
import com.android.server.print.RemotePrintSpooler.PrintSpoolerCallbacks;
import com.android.server.print.RemotePrintServiceRecommendationService.RemotePrintServiceRecommendationServiceCallbacks;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Represents the print state for a user.
 */
final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
        RemotePrintServiceRecommendationServiceCallbacks {

    private static final String LOG_TAG = "UserState";

    private static final boolean DEBUG = false;

    private static final char COMPONENT_NAME_SEPARATOR = ':';

    private final SimpleStringSplitter mStringColonSplitter =
            new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);

    private final Intent mQueryIntent =
            new Intent(android.printservice.PrintService.SERVICE_INTERFACE);

    private final ArrayMap<ComponentName, RemotePrintService> mActiveServices =
            new ArrayMap<ComponentName, RemotePrintService>();

    private final List<PrintServiceInfo> mInstalledServices =
            new ArrayList<PrintServiceInfo>();

    private final Set<ComponentName> mDisabledServices =
            new ArraySet<ComponentName>();

    private final PrintJobForAppCache mPrintJobForAppCache =
            new PrintJobForAppCache();

    private final Object mLock;

    private final Context mContext;

    private final int mUserId;

    private final RemotePrintSpooler mSpooler;

    private final Handler mHandler;

    private PrinterDiscoverySessionMediator mPrinterDiscoverySession;

    private List<PrintJobStateChangeListenerRecord> mPrintJobStateChangeListenerRecords;

    private List<ListenerRecord<IPrintServicesChangeListener>> mPrintServicesChangeListenerRecords;

    private List<ListenerRecord<IRecommendationsChangeListener>>
            mPrintServiceRecommendationsChangeListenerRecords;

    private boolean mDestroyed;

    /** Currently known list of print service recommendations */
    private List<RecommendationInfo> mPrintServiceRecommendations;

    /**
     * Connection to the service updating the {@link #mPrintServiceRecommendations print service
     * recommendations}.
     */
    private RemotePrintServiceRecommendationService mPrintServiceRecommendationsService;

    public UserState(Context context, int userId, Object lock, boolean lowPriority) {
        mContext = context;
        mUserId = userId;
        mLock = lock;
        mSpooler = new RemotePrintSpooler(context, userId, lowPriority, this);
        mHandler = new UserStateHandler(context.getMainLooper());

        synchronized (mLock) {
            readInstalledPrintServicesLocked();
            upgradePersistentStateIfNeeded();
            readDisabledPrintServicesLocked();

            // Some print services might have gotten installed before the User State came up
            prunePrintServices();

            onConfigurationChangedLocked();
        }
    }

    public void increasePriority() {
        mSpooler.increasePriority();
    }

    @Override
    public void onPrintJobQueued(PrintJobInfo printJob) {
        final RemotePrintService service;
        synchronized (mLock) {
            throwIfDestroyedLocked();
            ComponentName printServiceName = printJob.getPrinterId().getServiceName();
            service = mActiveServices.get(printServiceName);
        }
        if (service != null) {
            service.onPrintJobQueued(printJob);
        } else {
            // The service for the job is no longer enabled, so just
            // fail the job with the appropriate message.
            mSpooler.setPrintJobState(printJob.getId(), PrintJobInfo.STATE_FAILED,
                    mContext.getString(R.string.reason_service_unavailable));
        }
    }

    @Override
    public void onAllPrintJobsForServiceHandled(ComponentName printService) {
        final RemotePrintService service;
        synchronized (mLock) {
            throwIfDestroyedLocked();
            service = mActiveServices.get(printService);
        }
        if (service != null) {
            service.onAllPrintJobsHandled();
        }
    }

    public void removeObsoletePrintJobs() {
        mSpooler.removeObsoletePrintJobs();
    }

    @SuppressWarnings("deprecation")
    public Bundle print(@NonNull String printJobName, @NonNull IPrintDocumentAdapter adapter,
            @Nullable PrintAttributes attributes, @NonNull String packageName, int appId) {
        // Create print job place holder.
        final PrintJobInfo printJob = new PrintJobInfo();
        printJob.setId(new PrintJobId());
        printJob.setAppId(appId);
        printJob.setLabel(printJobName);
        printJob.setAttributes(attributes);
        printJob.setState(PrintJobInfo.STATE_CREATED);
        printJob.setCopies(1);
        printJob.setCreationTime(System.currentTimeMillis());

        // Track this job so we can forget it when the creator dies.
        if (!mPrintJobForAppCache.onPrintJobCreated(adapter.asBinder(), appId,
                printJob)) {
            // Not adding a print job means the client is dead - done.
            return null;
        }

        // Spin the spooler to add the job and show the config UI.
        new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... params) {
                mSpooler.createPrintJob(printJob);
                return null;
            }
        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);

        final long identity = Binder.clearCallingIdentity();
        try {
            Intent intent = new Intent(PrintManager.ACTION_PRINT_DIALOG);
            intent.setData(Uri.fromParts("printjob", printJob.getId().flattenToString(), null));
            intent.putExtra(PrintManager.EXTRA_PRINT_DOCUMENT_ADAPTER, adapter.asBinder());
            intent.putExtra(PrintManager.EXTRA_PRINT_JOB, printJob);
            intent.putExtra(DocumentsContract.EXTRA_PACKAGE_NAME, packageName);

            IntentSender intentSender = PendingIntent.getActivityAsUser(
                    mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT
                    | PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE,
                    null, new UserHandle(mUserId)) .getIntentSender();

            Bundle result = new Bundle();
            result.putParcelable(PrintManager.EXTRA_PRINT_JOB, printJob);
            result.putParcelable(PrintManager.EXTRA_PRINT_DIALOG_INTENT, intentSender);

            return result;
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    public List<PrintJobInfo> getPrintJobInfos(int appId) {
        List<PrintJobInfo> cachedPrintJobs = mPrintJobForAppCache.getPrintJobs(appId);
        // Note that the print spooler is not storing print jobs that
        // are in a terminal state as it is non-trivial to properly update
        // the spooler state for when to forget print jobs in terminal state.
        // Therefore, we fuse the cached print jobs for running apps (some
        // jobs are in a terminal state) with the ones that the print
        // spooler knows about (some jobs are being processed).
        ArrayMap<PrintJobId, PrintJobInfo> result =
                new ArrayMap<PrintJobId, PrintJobInfo>();

        // Add the cached print jobs for running apps.
        final int cachedPrintJobCount = cachedPrintJobs.size();
        for (int i = 0; i < cachedPrintJobCount; i++) {
            PrintJobInfo cachedPrintJob = cachedPrintJobs.get(i);
            result.put(cachedPrintJob.getId(), cachedPrintJob);
            // Strip out the tag and the advanced print options.
            // They are visible only to print services.
            cachedPrintJob.setTag(null);
            cachedPrintJob.setAdvancedOptions(null);
        }

        // Add everything else the spooler knows about.
        List<PrintJobInfo> printJobs = mSpooler.getPrintJobInfos(null,
                PrintJobInfo.STATE_ANY, appId);
        if (printJobs != null) {
            final int printJobCount = printJobs.size();
            for (int i = 0; i < printJobCount; i++) {
                PrintJobInfo printJob = printJobs.get(i);
                result.put(printJob.getId(), printJob);
                // Strip out the tag and the advanced print options.
                // They are visible only to print services.
                printJob.setTag(null);
                printJob.setAdvancedOptions(null);
            }
        }

        return new ArrayList<PrintJobInfo>(result.values());
    }

    public PrintJobInfo getPrintJobInfo(@NonNull PrintJobId printJobId, int appId) {
        PrintJobInfo printJob = mPrintJobForAppCache.getPrintJob(printJobId, appId);
        if (printJob == null) {
            printJob = mSpooler.getPrintJobInfo(printJobId, appId);
        }
        if (printJob != null) {
            // Strip out the tag and the advanced print options.
            // They are visible only to print services.
            printJob.setTag(null);
            printJob.setAdvancedOptions(null);
        }
        return printJob;
    }

    /**
     * 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()
     */
    public @Nullable Icon getCustomPrinterIcon(@NonNull PrinterId printerId) {
        Icon icon = mSpooler.getCustomPrinterIcon(printerId);

        if (icon == null) {
            RemotePrintService service = mActiveServices.get(printerId.getServiceName());
            if (service != null) {
                service.requestCustomPrinterIcon(printerId);
            }
        }

        return icon;
    }

    public void cancelPrintJob(@NonNull PrintJobId printJobId, int appId) {
        PrintJobInfo printJobInfo = mSpooler.getPrintJobInfo(printJobId, appId);
        if (printJobInfo == null) {
            return;
        }

        // Take a note that we are trying to cancel the job.
        mSpooler.setPrintJobCancelling(printJobId, true);

        if (printJobInfo.getState() != PrintJobInfo.STATE_FAILED) {
            PrinterId printerId = printJobInfo.getPrinterId();

            if (printerId != null) {
                ComponentName printServiceName = printerId.getServiceName();
                RemotePrintService printService = null;
                synchronized (mLock) {
                    printService = mActiveServices.get(printServiceName);
                }
                if (printService == null) {
                    return;
                }
                printService.onRequestCancelPrintJob(printJobInfo);
            }
        } else {
            // If the print job is failed we do not need cooperation
            // from the print service.
            mSpooler.setPrintJobState(printJobId, PrintJobInfo.STATE_CANCELED, null);
        }
    }

    public void restartPrintJob(@NonNull PrintJobId printJobId, int appId) {
        PrintJobInfo printJobInfo = getPrintJobInfo(printJobId, appId);
        if (printJobInfo == null || printJobInfo.getState() != PrintJobInfo.STATE_FAILED) {
            return;
        }
        mSpooler.setPrintJobState(printJobId, PrintJobInfo.STATE_QUEUED, null);
    }

    public @Nullable List<PrintServiceInfo> getPrintServices(int selectionFlags) {
        synchronized (mLock) {
            List<PrintServiceInfo> selectedServices = null;
            final int installedServiceCount = mInstalledServices.size();
            for (int i = 0; i < installedServiceCount; i++) {
                PrintServiceInfo installedService = mInstalledServices.get(i);

                ComponentName componentName = new ComponentName(
                        installedService.getResolveInfo().serviceInfo.packageName,
                        installedService.getResolveInfo().serviceInfo.name);

                // Update isEnabled under the same lock the final returned list is created
                installedService.setIsEnabled(mActiveServices.containsKey(componentName));

                if (installedService.isEnabled()) {
                    if ((selectionFlags & PrintManager.ENABLED_SERVICES) == 0) {
                        continue;
                    }
                } else {
                    if ((selectionFlags & PrintManager.DISABLED_SERVICES) == 0) {
                        continue;
                    }
                }

                if (selectedServices == null) {
                    selectedServices = new ArrayList<>();
                }
                selectedServices.add(installedService);
            }
            return selectedServices;
        }
    }

    public void setPrintServiceEnabled(@NonNull ComponentName serviceName, boolean isEnabled) {
        synchronized (mLock) {
            boolean isChanged = false;
            if (isEnabled) {
                isChanged = mDisabledServices.remove(serviceName);
            } else {
                // Make sure to only disable services that are currently installed
                final int numServices = mInstalledServices.size();
                for (int i = 0; i < numServices; i++) {
                    PrintServiceInfo service = mInstalledServices.get(i);

                    if (service.getComponentName().equals(serviceName)) {
                        mDisabledServices.add(serviceName);
                        isChanged = true;
                        break;
                    }
                }
            }

            if (isChanged) {
                writeDisabledPrintServicesLocked(mDisabledServices);

                onConfigurationChangedLocked();
            }
        }
    }

    /**
     * @return The currently known print service recommendations
     */
    public @Nullable List<RecommendationInfo> getPrintServiceRecommendations() {
        return mPrintServiceRecommendations;
    }

    public void createPrinterDiscoverySession(@NonNull IPrinterDiscoveryObserver observer) {
        synchronized (mLock) {
            throwIfDestroyedLocked();

            if (mPrinterDiscoverySession == null) {
                mSpooler.clearCustomPrinterIconCache();

                // If we do not have a session, tell all service to create one.
                mPrinterDiscoverySession = new PrinterDiscoverySessionMediator(mContext) {
                    @Override
                    public void onDestroyed() {
                        mPrinterDiscoverySession = null;
                    }
                };
                // Add the observer to the brand new session.
                mPrinterDiscoverySession.addObserverLocked(observer);
            } else {
                // If services have created session, just add the observer.
                mPrinterDiscoverySession.addObserverLocked(observer);
            }
        }
    }

    public void destroyPrinterDiscoverySession(@NonNull IPrinterDiscoveryObserver observer) {
        synchronized (mLock) {
            // Already destroyed - nothing to do.
            if (mPrinterDiscoverySession == null) {
                return;
            }
            // Remove this observer.
            mPrinterDiscoverySession.removeObserverLocked(observer);
        }
    }

    public void startPrinterDiscovery(@NonNull IPrinterDiscoveryObserver observer,
            @Nullable List<PrinterId> printerIds) {
        synchronized (mLock) {
            throwIfDestroyedLocked();

            // No session - nothing to do.
            if (mPrinterDiscoverySession == null) {
                return;
            }
            // Kick of discovery.
            mPrinterDiscoverySession.startPrinterDiscoveryLocked(observer,
                    printerIds);
        }
    }

    public void stopPrinterDiscovery(@NonNull IPrinterDiscoveryObserver observer) {
        synchronized (mLock) {
            throwIfDestroyedLocked();

            // No session - nothing to do.
            if (mPrinterDiscoverySession == null) {
                return;
            }
            // Kick of discovery.
            mPrinterDiscoverySession.stopPrinterDiscoveryLocked(observer);
        }
    }

    public void validatePrinters(@NonNull List<PrinterId> printerIds) {
        synchronized (mLock) {
            throwIfDestroyedLocked();
            // No services - nothing to do.
            if (mActiveServices.isEmpty()) {
                return;
            }
            // No session - nothing to do.
            if (mPrinterDiscoverySession == null) {
                return;
            }
            // Request an updated.
            mPrinterDiscoverySession.validatePrintersLocked(printerIds);
        }
    }

    public void startPrinterStateTracking(@NonNull PrinterId printerId) {
        synchronized (mLock) {
            throwIfDestroyedLocked();
            // No services - nothing to do.
            if (mActiveServices.isEmpty()) {
                return;
            }
            // No session - nothing to do.
            if (mPrinterDiscoverySession == null) {
                return;
            }
            // Request start tracking the printer.
            mPrinterDiscoverySession.startPrinterStateTrackingLocked(printerId);
        }
    }

    public void stopPrinterStateTracking(PrinterId printerId) {
        synchronized (mLock) {
            throwIfDestroyedLocked();
            // No services - nothing to do.
            if (mActiveServices.isEmpty()) {
                return;
            }
            // No session - nothing to do.
            if (mPrinterDiscoverySession == null) {
                return;
            }
            // Request stop tracking the printer.
            mPrinterDiscoverySession.stopPrinterStateTrackingLocked(printerId);
        }
    }

    public void addPrintJobStateChangeListener(@NonNull IPrintJobStateChangeListener listener,
            int appId) throws RemoteException {
        synchronized (mLock) {
            throwIfDestroyedLocked();
            if (mPrintJobStateChangeListenerRecords == null) {
                mPrintJobStateChangeListenerRecords =
                        new ArrayList<PrintJobStateChangeListenerRecord>();
            }
            mPrintJobStateChangeListenerRecords.add(
                    new PrintJobStateChangeListenerRecord(listener, appId) {
                @Override
                public void onBinderDied() {
                    synchronized (mLock) {
                        if (mPrintJobStateChangeListenerRecords != null) {
                            mPrintJobStateChangeListenerRecords.remove(this);
                        }
                    }
                }
            });
        }
    }

    public void removePrintJobStateChangeListener(@NonNull IPrintJobStateChangeListener listener) {
        synchronized (mLock) {
            throwIfDestroyedLocked();
            if (mPrintJobStateChangeListenerRecords == null) {
                return;
            }
            final int recordCount = mPrintJobStateChangeListenerRecords.size();
            for (int i = 0; i < recordCount; i++) {
                PrintJobStateChangeListenerRecord record =
                        mPrintJobStateChangeListenerRecords.get(i);
                if (record.listener.asBinder().equals(listener.asBinder())) {
                    mPrintJobStateChangeListenerRecords.remove(i);
                    break;
                }
            }
            if (mPrintJobStateChangeListenerRecords.isEmpty()) {
                mPrintJobStateChangeListenerRecords = null;
            }
        }
    }

    public void addPrintServicesChangeListener(@NonNull IPrintServicesChangeListener listener)
            throws RemoteException {
        synchronized (mLock) {
            throwIfDestroyedLocked();
            if (mPrintServicesChangeListenerRecords == null) {
                mPrintServicesChangeListenerRecords = new ArrayList<>();
            }
            mPrintServicesChangeListenerRecords.add(
                    new ListenerRecord<IPrintServicesChangeListener>(listener) {
                        @Override
                        public void onBinderDied() {
                            synchronized (mLock) {
                                if (mPrintServicesChangeListenerRecords != null) {
                                    mPrintServicesChangeListenerRecords.remove(this);
                                }
                            }
                        }
                    });
        }
    }

    public void removePrintServicesChangeListener(@NonNull IPrintServicesChangeListener listener) {
        synchronized (mLock) {
            throwIfDestroyedLocked();
            if (mPrintServicesChangeListenerRecords == null) {
                return;
            }
            final int recordCount = mPrintServicesChangeListenerRecords.size();
            for (int i = 0; i < recordCount; i++) {
                ListenerRecord<IPrintServicesChangeListener> record =
                        mPrintServicesChangeListenerRecords.get(i);
                if (record.listener.asBinder().equals(listener.asBinder())) {
                    mPrintServicesChangeListenerRecords.remove(i);
                    break;
                }
            }
            if (mPrintServicesChangeListenerRecords.isEmpty()) {
                mPrintServicesChangeListenerRecords = null;
            }
        }
    }

    public void addPrintServiceRecommendationsChangeListener(
            @NonNull IRecommendationsChangeListener listener) throws RemoteException {
        synchronized (mLock) {
            throwIfDestroyedLocked();
            if (mPrintServiceRecommendationsChangeListenerRecords == null) {
                mPrintServiceRecommendationsChangeListenerRecords = new ArrayList<>();

                mPrintServiceRecommendationsService =
                        new RemotePrintServiceRecommendationService(mContext,
                                UserHandle.getUserHandleForUid(mUserId), this);
            }
            mPrintServiceRecommendationsChangeListenerRecords.add(
                    new ListenerRecord<IRecommendationsChangeListener>(listener) {
                        @Override
                        public void onBinderDied() {
                            synchronized (mLock) {
                                if (mPrintServiceRecommendationsChangeListenerRecords != null) {
                                    mPrintServiceRecommendationsChangeListenerRecords.remove(this);
                                }
                            }
                        }
                    });
        }
    }

    public void removePrintServiceRecommendationsChangeListener(
            @NonNull IRecommendationsChangeListener listener) {
        synchronized (mLock) {
            throwIfDestroyedLocked();
            if (mPrintServiceRecommendationsChangeListenerRecords == null) {
                return;
            }
            final int recordCount = mPrintServiceRecommendationsChangeListenerRecords.size();
            for (int i = 0; i < recordCount; i++) {
                ListenerRecord<IRecommendationsChangeListener> record =
                        mPrintServiceRecommendationsChangeListenerRecords.get(i);
                if (record.listener.asBinder().equals(listener.asBinder())) {
                    mPrintServiceRecommendationsChangeListenerRecords.remove(i);
                    break;
                }
            }
            if (mPrintServiceRecommendationsChangeListenerRecords.isEmpty()) {
                mPrintServiceRecommendationsChangeListenerRecords = null;

                mPrintServiceRecommendations = null;

                mPrintServiceRecommendationsService.close();
                mPrintServiceRecommendationsService = null;
            }
        }
    }

    @Override
    public void onPrintJobStateChanged(PrintJobInfo printJob) {
        mPrintJobForAppCache.onPrintJobStateChanged(printJob);
        mHandler.obtainMessage(UserStateHandler.MSG_DISPATCH_PRINT_JOB_STATE_CHANGED,
                printJob.getAppId(), 0, printJob.getId()).sendToTarget();
    }

    public void onPrintServicesChanged() {
        mHandler.obtainMessage(UserStateHandler.MSG_DISPATCH_PRINT_SERVICES_CHANGED).sendToTarget();
    }

    @Override
    public void onPrintServiceRecommendationsUpdated(List<RecommendationInfo> recommendations) {
        mHandler.obtainMessage(UserStateHandler.MSG_DISPATCH_PRINT_SERVICES_RECOMMENDATIONS_UPDATED,
                0, 0, recommendations).sendToTarget();
    }

    @Override
    public void onPrintersAdded(List<PrinterInfo> printers) {
        synchronized (mLock) {
            throwIfDestroyedLocked();
            // No services - nothing to do.
            if (mActiveServices.isEmpty()) {
                return;
            }
            // No session - nothing to do.
            if (mPrinterDiscoverySession == null) {
                return;
            }
            mPrinterDiscoverySession.onPrintersAddedLocked(printers);
        }
    }

    @Override
    public void onPrintersRemoved(List<PrinterId> printerIds) {
        synchronized (mLock) {
            throwIfDestroyedLocked();
            // No services - nothing to do.
            if (mActiveServices.isEmpty()) {
                return;
            }
            // No session - nothing to do.
            if (mPrinterDiscoverySession == null) {
                return;
            }
            mPrinterDiscoverySession.onPrintersRemovedLocked(printerIds);
        }
    }

    @Override
    public void onCustomPrinterIconLoaded(PrinterId printerId, Icon icon) {
        synchronized (mLock) {
            throwIfDestroyedLocked();

            // No session - nothing to do.
            if (mPrinterDiscoverySession == null) {
                return;
            }
            mSpooler.onCustomPrinterIconLoaded(printerId, icon);
            mPrinterDiscoverySession.onCustomPrinterIconLoadedLocked(printerId);
        }
    }

    @Override
    public void onServiceDied(RemotePrintService service) {
        synchronized (mLock) {
            throwIfDestroyedLocked();
            // No services - nothing to do.
            if (mActiveServices.isEmpty()) {
                return;
            }
            // Fail all print jobs.
            failActivePrintJobsForService(service.getComponentName());
            service.onAllPrintJobsHandled();
            // No session - nothing to do.
            if (mPrinterDiscoverySession == null) {
                return;
            }
            mPrinterDiscoverySession.onServiceDiedLocked(service);
        }
    }

    public void updateIfNeededLocked() {
        throwIfDestroyedLocked();
        readConfigurationLocked();
        onConfigurationChangedLocked();
    }

    public void destroyLocked() {
        throwIfDestroyedLocked();
        mSpooler.destroy();
        for (RemotePrintService service : mActiveServices.values()) {
            service.destroy();
        }
        mActiveServices.clear();
        mInstalledServices.clear();
        mDisabledServices.clear();
        if (mPrinterDiscoverySession != null) {
            mPrinterDiscoverySession.destroyLocked();
            mPrinterDiscoverySession = null;
        }
        mDestroyed = true;
    }

    public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String prefix) {
        pw.append(prefix).append("user state ").append(String.valueOf(mUserId)).append(":");
        pw.println();

        String tab = "  ";

        pw.append(prefix).append(tab).append("installed services:").println();
        final int installedServiceCount = mInstalledServices.size();
        for (int i = 0; i < installedServiceCount; i++) {
            PrintServiceInfo installedService = mInstalledServices.get(i);
            String installedServicePrefix = prefix + tab + tab;
            pw.append(installedServicePrefix).append("service:").println();
            ResolveInfo resolveInfo = installedService.getResolveInfo();
            ComponentName componentName = new ComponentName(
                    resolveInfo.serviceInfo.packageName,
                    resolveInfo.serviceInfo.name);
            pw.append(installedServicePrefix).append(tab).append("componentName=")
                    .append(componentName.flattenToString()).println();
            pw.append(installedServicePrefix).append(tab).append("settingsActivity=")
                    .append(installedService.getSettingsActivityName()).println();
            pw.append(installedServicePrefix).append(tab).append("addPrintersActivity=")
                    .append(installedService.getAddPrintersActivityName()).println();
            pw.append(installedServicePrefix).append(tab).append("avancedOptionsActivity=")
                   .append(installedService.getAdvancedOptionsActivityName()).println();
        }

        pw.append(prefix).append(tab).append("disabled services:").println();
        for (ComponentName disabledService : mDisabledServices) {
            String disabledServicePrefix = prefix + tab + tab;
            pw.append(disabledServicePrefix).append("service:").println();
            pw.append(disabledServicePrefix).append(tab).append("componentName=")
                    .append(disabledService.flattenToString());
            pw.println();
        }

        pw.append(prefix).append(tab).append("active services:").println();
        final int activeServiceCount = mActiveServices.size();
        for (int i = 0; i < activeServiceCount; i++) {
            RemotePrintService activeService = mActiveServices.valueAt(i);
            activeService.dump(pw, prefix + tab + tab);
            pw.println();
        }

        pw.append(prefix).append(tab).append("cached print jobs:").println();
        mPrintJobForAppCache.dump(pw, prefix + tab + tab);

        pw.append(prefix).append(tab).append("discovery mediator:").println();
        if (mPrinterDiscoverySession != null) {
            mPrinterDiscoverySession.dump(pw, prefix + tab + tab);
        }

        pw.append(prefix).append(tab).append("print spooler:").println();
        mSpooler.dump(fd, pw, prefix + tab + tab);
        pw.println();
    }

    private void readConfigurationLocked() {
        readInstalledPrintServicesLocked();
        readDisabledPrintServicesLocked();
    }

    private void readInstalledPrintServicesLocked() {
        Set<PrintServiceInfo> tempPrintServices = new HashSet<PrintServiceInfo>();

        List<ResolveInfo> installedServices = mContext.getPackageManager()
                .queryIntentServicesAsUser(mQueryIntent,
                        GET_SERVICES | GET_META_DATA | MATCH_DEBUG_TRIAGED_MISSING, mUserId);

        final int installedCount = installedServices.size();
        for (int i = 0, count = installedCount; i < count; i++) {
            ResolveInfo installedService = installedServices.get(i);
            if (!android.Manifest.permission.BIND_PRINT_SERVICE.equals(
                    installedService.serviceInfo.permission)) {
                ComponentName serviceName = new ComponentName(
                        installedService.serviceInfo.packageName,
                        installedService.serviceInfo.name);
                Slog.w(LOG_TAG, "Skipping print service "
                        + serviceName.flattenToShortString()
                        + " since it does not require permission "
                        + android.Manifest.permission.BIND_PRINT_SERVICE);
                continue;
            }
            tempPrintServices.add(PrintServiceInfo.create(installedService, mContext));
        }

        mInstalledServices.clear();
        mInstalledServices.addAll(tempPrintServices);
    }

    /**
     * Update persistent state from a previous version of Android.
     */
    private void upgradePersistentStateIfNeeded() {
        String enabledSettingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(),
                Settings.Secure.ENABLED_PRINT_SERVICES, mUserId);

        // Pre N we store the enabled services, in N and later we store the disabled services.
        // Hence if enabledSettingValue is still set, we need to upgrade.
        if (enabledSettingValue != null) {
            Set<ComponentName> enabledServiceNameSet = new HashSet<ComponentName>();
            readPrintServicesFromSettingLocked(Settings.Secure.ENABLED_PRINT_SERVICES,
                    enabledServiceNameSet);

            ArraySet<ComponentName> disabledServices = new ArraySet<>();
            final int numInstalledServices = mInstalledServices.size();
            for (int i = 0; i < numInstalledServices; i++) {
                ComponentName serviceName = mInstalledServices.get(i).getComponentName();
                if (!enabledServiceNameSet.contains(serviceName)) {
                    disabledServices.add(serviceName);
                }
            }

            writeDisabledPrintServicesLocked(disabledServices);

            // We won't needed ENABLED_PRINT_SERVICES anymore, set to null to prevent upgrade to run
            // again.
            Settings.Secure.putStringForUser(mContext.getContentResolver(),
                    Settings.Secure.ENABLED_PRINT_SERVICES, null, mUserId);
        }
    }

    /**
     * Read the set of disabled print services from the secure settings.
     *
     * @return true if the state changed.
     */
    private void readDisabledPrintServicesLocked() {
        Set<ComponentName> tempDisabledServiceNameSet = new HashSet<ComponentName>();
        readPrintServicesFromSettingLocked(Settings.Secure.DISABLED_PRINT_SERVICES,
                tempDisabledServiceNameSet);
        if (!tempDisabledServiceNameSet.equals(mDisabledServices)) {
            mDisabledServices.clear();
            mDisabledServices.addAll(tempDisabledServiceNameSet);
        }
    }

    private void readPrintServicesFromSettingLocked(String setting,
            Set<ComponentName> outServiceNames) {
        String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(),
                setting, mUserId);
        if (!TextUtils.isEmpty(settingValue)) {
            TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
            splitter.setString(settingValue);
            while (splitter.hasNext()) {
                String string = splitter.next();
                if (TextUtils.isEmpty(string)) {
                    continue;
                }
                ComponentName componentName = ComponentName.unflattenFromString(string);
                if (componentName != null) {
                    outServiceNames.add(componentName);
                }
            }
        }
    }

    /**
     * Persist the disabled print services to the secure settings.
     */
    private void writeDisabledPrintServicesLocked(Set<ComponentName> disabledServices) {
        StringBuilder builder = new StringBuilder();
        for (ComponentName componentName : disabledServices) {
            if (builder.length() > 0) {
                builder.append(COMPONENT_NAME_SEPARATOR);
            }
            builder.append(componentName.flattenToShortString());
        }
        Settings.Secure.putStringForUser(mContext.getContentResolver(),
                Settings.Secure.DISABLED_PRINT_SERVICES, builder.toString(), mUserId);
    }

    /**
     * Get the {@link ComponentName names} of the installed print services
     *
     * @return The names of the installed print services
     */
    private ArrayList<ComponentName> getInstalledComponents() {
        ArrayList<ComponentName> installedComponents = new ArrayList<ComponentName>();

        final int installedCount = mInstalledServices.size();
        for (int i = 0; i < installedCount; i++) {
            ResolveInfo resolveInfo = mInstalledServices.get(i).getResolveInfo();
            ComponentName serviceName = new ComponentName(resolveInfo.serviceInfo.packageName,
                    resolveInfo.serviceInfo.name);

            installedComponents.add(serviceName);
        }

        return installedComponents;
    }

    /**
     * Prune persistent state if a print service was uninstalled
     */
    public void prunePrintServices() {
        synchronized (mLock) {
            ArrayList<ComponentName> installedComponents = getInstalledComponents();

            // Remove unnecessary entries from persistent state "disabled services"
            boolean disabledServicesUninstalled = mDisabledServices.retainAll(installedComponents);
            if (disabledServicesUninstalled) {
                writeDisabledPrintServicesLocked(mDisabledServices);
            }

            // Remove unnecessary entries from persistent state "approved services"
            mSpooler.pruneApprovedPrintServices(installedComponents);
        }
    }

    private void onConfigurationChangedLocked() {
        ArrayList<ComponentName> installedComponents = getInstalledComponents();

        final int installedCount = installedComponents.size();
        for (int i = 0; i < installedCount; i++) {
            ComponentName serviceName = installedComponents.get(i);

            if (!mDisabledServices.contains(serviceName)) {
                if (!mActiveServices.containsKey(serviceName)) {
                    RemotePrintService service = new RemotePrintService(
                            mContext, serviceName, mUserId, mSpooler, this);
                    addServiceLocked(service);
                }
            } else {
                RemotePrintService service = mActiveServices.remove(serviceName);
                if (service != null) {
                    removeServiceLocked(service);
                }
            }
        }

        Iterator<Map.Entry<ComponentName, RemotePrintService>> iterator =
                mActiveServices.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<ComponentName, RemotePrintService> entry = iterator.next();
            ComponentName serviceName = entry.getKey();
            RemotePrintService service = entry.getValue();
            if (!installedComponents.contains(serviceName)) {
                removeServiceLocked(service);
                iterator.remove();
            }
        }

        onPrintServicesChanged();
    }

    private void addServiceLocked(RemotePrintService service) {
        mActiveServices.put(service.getComponentName(), service);
        if (mPrinterDiscoverySession != null) {
            mPrinterDiscoverySession.onServiceAddedLocked(service);
        }
    }

    private void removeServiceLocked(RemotePrintService service) {
        // Fail all print jobs.
        failActivePrintJobsForService(service.getComponentName());
        // If discovery is in progress, tear down the service.
        if (mPrinterDiscoverySession != null) {
            mPrinterDiscoverySession.onServiceRemovedLocked(service);
        } else {
            // Otherwise, just destroy it.
            service.destroy();
        }
    }

    private void failActivePrintJobsForService(final ComponentName serviceName) {
        // Makes sure all active print jobs are failed since the service
        // just died. Do this off the main thread since we do to allow
        // calls into the spooler on the main thread.
        if (Looper.getMainLooper().isCurrentThread()) {
            BackgroundThread.getHandler().post(new Runnable() {
                @Override
                public void run() {
                    failScheduledPrintJobsForServiceInternal(serviceName);
                }
            });
        } else {
            failScheduledPrintJobsForServiceInternal(serviceName);
        }
    }

    private void failScheduledPrintJobsForServiceInternal(ComponentName serviceName) {
        List<PrintJobInfo> printJobs = mSpooler.getPrintJobInfos(serviceName,
                PrintJobInfo.STATE_ANY_SCHEDULED, PrintManager.APP_ID_ANY);
        if (printJobs == null) {
            return;
        }
        final long identity = Binder.clearCallingIdentity();
        try {
            final int printJobCount = printJobs.size();
            for (int i = 0; i < printJobCount; i++) {
                PrintJobInfo printJob = printJobs.get(i);
                mSpooler.setPrintJobState(printJob.getId(), PrintJobInfo.STATE_FAILED,
                        mContext.getString(R.string.reason_service_unavailable));
            }
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    private void throwIfDestroyedLocked() {
        if (mDestroyed) {
            throw new IllegalStateException("Cannot interact with a destroyed instance.");
        }
    }

    private void handleDispatchPrintJobStateChanged(PrintJobId printJobId, int appId) {
        final List<PrintJobStateChangeListenerRecord> records;
        synchronized (mLock) {
            if (mPrintJobStateChangeListenerRecords == null) {
                return;
            }
            records = new ArrayList<PrintJobStateChangeListenerRecord>(
                    mPrintJobStateChangeListenerRecords);
        }
        final int recordCount = records.size();
        for (int i = 0; i < recordCount; i++) {
            PrintJobStateChangeListenerRecord record = records.get(i);
            if (record.appId == PrintManager.APP_ID_ANY
                    || record.appId == appId)
            try {
                record.listener.onPrintJobStateChanged(printJobId);
            } catch (RemoteException re) {
                Log.e(LOG_TAG, "Error notifying for print job state change", re);
            }
        }
    }

    private void handleDispatchPrintServicesChanged() {
        final List<ListenerRecord<IPrintServicesChangeListener>> records;
        synchronized (mLock) {
            if (mPrintServicesChangeListenerRecords == null) {
                return;
            }
            records = new ArrayList<>(mPrintServicesChangeListenerRecords);
        }
        final int recordCount = records.size();
        for (int i = 0; i < recordCount; i++) {
            ListenerRecord<IPrintServicesChangeListener> record = records.get(i);

            try {
                record.listener.onPrintServicesChanged();;
            } catch (RemoteException re) {
                Log.e(LOG_TAG, "Error notifying for print services change", re);
            }
        }
    }

    private void handleDispatchPrintServiceRecommendationsUpdated(
            @Nullable List<RecommendationInfo> recommendations) {
        final List<ListenerRecord<IRecommendationsChangeListener>> records;
        synchronized (mLock) {
            if (mPrintServiceRecommendationsChangeListenerRecords == null) {
                return;
            }
            records = new ArrayList<>(mPrintServiceRecommendationsChangeListenerRecords);

            mPrintServiceRecommendations = recommendations;
        }
        final int recordCount = records.size();
        for (int i = 0; i < recordCount; i++) {
            ListenerRecord<IRecommendationsChangeListener> record = records.get(i);

            try {
                record.listener.onRecommendationsChanged();
            } catch (RemoteException re) {
                Log.e(LOG_TAG, "Error notifying for print service recommendations change", re);
            }
        }
    }

    private final class UserStateHandler extends Handler {
        public static final int MSG_DISPATCH_PRINT_JOB_STATE_CHANGED = 1;
        public static final int MSG_DISPATCH_PRINT_SERVICES_CHANGED = 2;
        public static final int MSG_DISPATCH_PRINT_SERVICES_RECOMMENDATIONS_UPDATED = 3;

        public UserStateHandler(Looper looper) {
            super(looper, null, false);
        }

        @Override
        public void handleMessage(Message message) {
            switch (message.what) {
                case MSG_DISPATCH_PRINT_JOB_STATE_CHANGED:
                    PrintJobId printJobId = (PrintJobId) message.obj;
                    final int appId = message.arg1;
                    handleDispatchPrintJobStateChanged(printJobId, appId);
                    break;
                case MSG_DISPATCH_PRINT_SERVICES_CHANGED:
                    handleDispatchPrintServicesChanged();
                    break;
                case MSG_DISPATCH_PRINT_SERVICES_RECOMMENDATIONS_UPDATED:
                    handleDispatchPrintServiceRecommendationsUpdated(
                            (List<RecommendationInfo>) message.obj);
                    break;
                default:
                    // not reached
            }
        }
    }

    private abstract class PrintJobStateChangeListenerRecord implements DeathRecipient {
        @NonNull final IPrintJobStateChangeListener listener;
        final int appId;

        public PrintJobStateChangeListenerRecord(@NonNull IPrintJobStateChangeListener listener,
                int appId) throws RemoteException {
            this.listener = listener;
            this.appId = appId;
            listener.asBinder().linkToDeath(this, 0);
        }

        @Override
        public void binderDied() {
            listener.asBinder().unlinkToDeath(this, 0);
            onBinderDied();
        }

        public abstract void onBinderDied();
    }

    private abstract class ListenerRecord<T extends IInterface> implements DeathRecipient {
        @NonNull final T listener;

        public ListenerRecord(@NonNull T listener) throws RemoteException {
            this.listener = listener;
            listener.asBinder().linkToDeath(this, 0);
        }

        @Override
        public void binderDied() {
            listener.asBinder().unlinkToDeath(this, 0);
            onBinderDied();
        }

        public abstract void onBinderDied();
    }

    private class PrinterDiscoverySessionMediator {
        private final ArrayMap<PrinterId, PrinterInfo> mPrinters =
                new ArrayMap<PrinterId, PrinterInfo>();

        private final RemoteCallbackList<IPrinterDiscoveryObserver> mDiscoveryObservers =
                new RemoteCallbackList<IPrinterDiscoveryObserver>() {
            @Override
            public void onCallbackDied(IPrinterDiscoveryObserver observer) {
                synchronized (mLock) {
                    stopPrinterDiscoveryLocked(observer);
                    removeObserverLocked(observer);
                }
            }
        };

        private final List<IBinder> mStartedPrinterDiscoveryTokens = new ArrayList<IBinder>();

        private final List<PrinterId> mStateTrackedPrinters = new ArrayList<PrinterId>();

        private final Handler mSessionHandler;

        private boolean mIsDestroyed;

        public PrinterDiscoverySessionMediator(Context context) {
            mSessionHandler = new SessionHandler(context.getMainLooper());
            // Kick off the session creation.
            List<RemotePrintService> services = new ArrayList<RemotePrintService>(
                    mActiveServices.values());
            mSessionHandler.obtainMessage(SessionHandler
                    .MSG_DISPATCH_CREATE_PRINTER_DISCOVERY_SESSION, services)
                    .sendToTarget();
        }

        public void addObserverLocked(@NonNull IPrinterDiscoveryObserver observer) {
            // Add the observer.
            mDiscoveryObservers.register(observer);

            // Bring the added observer up to speed with the printers.
            if (!mPrinters.isEmpty()) {
                List<PrinterInfo> printers = new ArrayList<PrinterInfo>(mPrinters.values());
                SomeArgs args = SomeArgs.obtain();
                args.arg1 = observer;
                args.arg2 = printers;
                mSessionHandler.obtainMessage(SessionHandler.MSG_PRINTERS_ADDED,
                        args).sendToTarget();
            }
        }

        public void removeObserverLocked(@NonNull IPrinterDiscoveryObserver observer) {
            // Remove the observer.
            mDiscoveryObservers.unregister(observer);
            // No one else observing - then kill it.
            if (mDiscoveryObservers.getRegisteredCallbackCount() == 0) {
                destroyLocked();
            }
        }

        public final void startPrinterDiscoveryLocked(@NonNull IPrinterDiscoveryObserver observer,
                @Nullable List<PrinterId> priorityList) {
            if (mIsDestroyed) {
                Log.w(LOG_TAG, "Not starting dicovery - session destroyed");
                return;
            }

            final boolean discoveryStarted = !mStartedPrinterDiscoveryTokens.isEmpty();

            // Remember we got a start request to match with an end.
            mStartedPrinterDiscoveryTokens.add(observer.asBinder());

            // If printer discovery is ongoing and the start request has a list
            // of printer to be checked, then we just request validating them.
            if (discoveryStarted && priorityList != null && !priorityList.isEmpty()) {
                validatePrinters(priorityList);
                return;
            }

            // The service are already performing discovery - nothing to do.
            if (mStartedPrinterDiscoveryTokens.size() > 1) {
                return;
            }

            List<RemotePrintService> services = new ArrayList<RemotePrintService>(
                    mActiveServices.values());
            SomeArgs args = SomeArgs.obtain();
            args.arg1 = services;
            args.arg2 = priorityList;
            mSessionHandler.obtainMessage(SessionHandler
                    .MSG_DISPATCH_START_PRINTER_DISCOVERY, args)
                    .sendToTarget();
        }

        public final void stopPrinterDiscoveryLocked(@NonNull IPrinterDiscoveryObserver observer) {
            if (mIsDestroyed) {
                Log.w(LOG_TAG, "Not stopping dicovery - session destroyed");
                return;
            }
            // This one did not make an active discovery request - nothing to do.
            if (!mStartedPrinterDiscoveryTokens.remove(observer.asBinder())) {
                return;
            }
            // There are other interested observers - do not stop discovery.
            if (!mStartedPrinterDiscoveryTokens.isEmpty()) {
                return;
            }
            List<RemotePrintService> services = new ArrayList<RemotePrintService>(
                    mActiveServices.values());
            mSessionHandler.obtainMessage(SessionHandler
                    .MSG_DISPATCH_STOP_PRINTER_DISCOVERY, services)
                    .sendToTarget();
        }

        public void validatePrintersLocked(@NonNull List<PrinterId> printerIds) {
            if (mIsDestroyed) {
                Log.w(LOG_TAG, "Not validating pritners - session destroyed");
                return;
            }

            List<PrinterId> remainingList = new ArrayList<PrinterId>(printerIds);
            while (!remainingList.isEmpty()) {
                Iterator<PrinterId> iterator = remainingList.iterator();
                // Gather the printers per service and request a validation.
                List<PrinterId> updateList = new ArrayList<PrinterId>();
                ComponentName serviceName = null;
                while (iterator.hasNext()) {
                    PrinterId printerId = iterator.next();
                    if (printerId != null) {
                        if (updateList.isEmpty()) {
                            updateList.add(printerId);
                            serviceName = printerId.getServiceName();
                            iterator.remove();
                        } else if (printerId.getServiceName().equals(serviceName)) {
                            updateList.add(printerId);
                            iterator.remove();
                        }
                    }
                }
                // Schedule a notification of the service.
                RemotePrintService service = mActiveServices.get(serviceName);
                if (service != null) {
                    SomeArgs args = SomeArgs.obtain();
                    args.arg1 = service;
                    args.arg2 = updateList;
                    mSessionHandler.obtainMessage(SessionHandler
                            .MSG_VALIDATE_PRINTERS, args)
                            .sendToTarget();
                }
            }
        }

        public final void startPrinterStateTrackingLocked(@NonNull PrinterId printerId) {
            if (mIsDestroyed) {
                Log.w(LOG_TAG, "Not starting printer state tracking - session destroyed");
                return;
            }
            // If printer discovery is not started - nothing to do.
            if (mStartedPrinterDiscoveryTokens.isEmpty()) {
                return;
            }
            final boolean containedPrinterId = mStateTrackedPrinters.contains(printerId);
            // Keep track of the number of requests to track this one.
            mStateTrackedPrinters.add(printerId);
            // If we were tracking this printer - nothing to do.
            if (containedPrinterId) {
                return;
            }
            // No service - nothing to do.
            RemotePrintService service = mActiveServices.get(printerId.getServiceName());
            if (service == null) {
                return;
            }
            // Ask the service to start tracking.
            SomeArgs args = SomeArgs.obtain();
            args.arg1 = service;
            args.arg2 = printerId;
            mSessionHandler.obtainMessage(SessionHandler
                    .MSG_START_PRINTER_STATE_TRACKING, args)
                    .sendToTarget();
        }

        public final void stopPrinterStateTrackingLocked(PrinterId printerId) {
            if (mIsDestroyed) {
                Log.w(LOG_TAG, "Not stopping printer state tracking - session destroyed");
                return;
            }
            // If printer discovery is not started - nothing to do.
            if (mStartedPrinterDiscoveryTokens.isEmpty()) {
                return;
            }
            // If we did not track this printer - nothing to do.
            if (!mStateTrackedPrinters.remove(printerId)) {
                return;
            }
            // No service - nothing to do.
            RemotePrintService service = mActiveServices.get(printerId.getServiceName());
            if (service == null) {
                return;
            }
            // Ask the service to start tracking.
            SomeArgs args = SomeArgs.obtain();
            args.arg1 = service;
            args.arg2 = printerId;
            mSessionHandler.obtainMessage(SessionHandler
                    .MSG_STOP_PRINTER_STATE_TRACKING, args)
                    .sendToTarget();
        }

        public void onDestroyed() {
            /* do nothing */
        }

        public void destroyLocked() {
            if (mIsDestroyed) {
                Log.w(LOG_TAG, "Not destroying - session destroyed");
                return;
            }
            mIsDestroyed = true;
            // Make sure printer tracking is stopped.
            final int printerCount = mStateTrackedPrinters.size();
            for (int i = 0; i < printerCount; i++) {
                PrinterId printerId = mStateTrackedPrinters.get(i);
                stopPrinterStateTracking(printerId);
            }
            // Make sure discovery is stopped.
            final int observerCount = mStartedPrinterDiscoveryTokens.size();
            for (int i = 0; i < observerCount; i++) {
                IBinder token = mStartedPrinterDiscoveryTokens.get(i);
                stopPrinterDiscoveryLocked(IPrinterDiscoveryObserver.Stub.asInterface(token));
            }
            // Tell the services we are done.
            List<RemotePrintService> services = new ArrayList<RemotePrintService>(
                    mActiveServices.values());
            mSessionHandler.obtainMessage(SessionHandler
                    .MSG_DISPATCH_DESTROY_PRINTER_DISCOVERY_SESSION, services)
                    .sendToTarget();
        }

        public void onPrintersAddedLocked(List<PrinterInfo> printers) {
            if (DEBUG) {
                Log.i(LOG_TAG, "onPrintersAddedLocked()");
            }
            if (mIsDestroyed) {
                Log.w(LOG_TAG, "Not adding printers - session destroyed");
                return;
            }
            List<PrinterInfo> addedPrinters = null;
            final int addedPrinterCount = printers.size();
            for (int i = 0; i < addedPrinterCount; i++) {
                PrinterInfo printer = printers.get(i);
                PrinterInfo oldPrinter = mPrinters.put(printer.getId(), printer);
                if (oldPrinter == null || !oldPrinter.equals(printer)) {
                    if (addedPrinters == null) {
                        addedPrinters = new ArrayList<PrinterInfo>();
                    }
                    addedPrinters.add(printer);
                }
            }
            if (addedPrinters != null) {
                mSessionHandler.obtainMessage(SessionHandler.MSG_DISPATCH_PRINTERS_ADDED,
                        addedPrinters).sendToTarget();
            }
        }

        public void onPrintersRemovedLocked(List<PrinterId> printerIds) {
            if (DEBUG) {
                Log.i(LOG_TAG, "onPrintersRemovedLocked()");
            }
            if (mIsDestroyed) {
                Log.w(LOG_TAG, "Not removing printers - session destroyed");
                return;
            }
            List<PrinterId> removedPrinterIds = null;
            final int removedPrinterCount = printerIds.size();
            for (int i = 0; i < removedPrinterCount; i++) {
                PrinterId removedPrinterId = printerIds.get(i);
                if (mPrinters.remove(removedPrinterId) != null) {
                    if (removedPrinterIds == null) {
                        removedPrinterIds = new ArrayList<PrinterId>();
                    }
                    removedPrinterIds.add(removedPrinterId);
                }
            }
            if (removedPrinterIds != null) {
                mSessionHandler.obtainMessage(SessionHandler.MSG_DISPATCH_PRINTERS_REMOVED,
                        removedPrinterIds).sendToTarget();
            }
        }

        public void onServiceRemovedLocked(RemotePrintService service) {
            if (mIsDestroyed) {
                Log.w(LOG_TAG, "Not updating removed service - session destroyed");
                return;
            }
            // Remove the reported and tracked printers for that service.
            ComponentName serviceName = service.getComponentName();
            removePrintersForServiceLocked(serviceName);
            service.destroy();
        }

        /**
         * Handle that a custom icon for a printer was loaded.
         *
         * This increments the icon generation and adds the printer again which triggers an update
         * in all users of the currently known printers.
         *
         * @param printerId the id of the printer the icon belongs to
         * @see android.print.PrinterInfo.Builder#setHasCustomPrinterIcon()
         */
        public void onCustomPrinterIconLoadedLocked(PrinterId printerId) {
            if (DEBUG) {
                Log.i(LOG_TAG, "onCustomPrinterIconLoadedLocked()");
            }
            if (mIsDestroyed) {
                Log.w(LOG_TAG, "Not updating printer - session destroyed");
                return;
            }

            PrinterInfo printer = mPrinters.get(printerId);
            if (printer != null) {
                PrinterInfo newPrinter = (new PrinterInfo.Builder(printer))
                        .incCustomPrinterIconGen().build();
                mPrinters.put(printerId, newPrinter);

                ArrayList<PrinterInfo> addedPrinters = new ArrayList<>(1);
                addedPrinters.add(newPrinter);
                mSessionHandler.obtainMessage(SessionHandler.MSG_DISPATCH_PRINTERS_ADDED,
                        addedPrinters).sendToTarget();
            }
        }

        public void onServiceDiedLocked(RemotePrintService service) {
            // Remove the reported by that service.
            removePrintersForServiceLocked(service.getComponentName());
        }

        public void onServiceAddedLocked(RemotePrintService service) {
            if (mIsDestroyed) {
                Log.w(LOG_TAG, "Not updating added service - session destroyed");
                return;
            }
            // Tell the service to create a session.
            mSessionHandler.obtainMessage(
                    SessionHandler.MSG_CREATE_PRINTER_DISCOVERY_SESSION,
                    service).sendToTarget();
            // Start printer discovery if necessary.
            if (!mStartedPrinterDiscoveryTokens.isEmpty()) {
                mSessionHandler.obtainMessage(
                        SessionHandler.MSG_START_PRINTER_DISCOVERY,
                        service).sendToTarget();
            }
            // Start tracking printers if necessary
            final int trackedPrinterCount = mStateTrackedPrinters.size();
            for (int i = 0; i < trackedPrinterCount; i++) {
                PrinterId printerId = mStateTrackedPrinters.get(i);
                if (printerId.getServiceName().equals(service.getComponentName())) {
                    SomeArgs args = SomeArgs.obtain();
                    args.arg1 = service;
                    args.arg2 = printerId;
                    mSessionHandler.obtainMessage(SessionHandler
                            .MSG_START_PRINTER_STATE_TRACKING, args)
                            .sendToTarget();
                }
            }
        }

        public void dump(PrintWriter pw, String prefix) {
            pw.append(prefix).append("destroyed=")
                    .append(String.valueOf(mDestroyed)).println();

            pw.append(prefix).append("printDiscoveryInProgress=")
                    .append(String.valueOf(!mStartedPrinterDiscoveryTokens.isEmpty())).println();

            String tab = "  ";

            pw.append(prefix).append(tab).append("printer discovery observers:").println();
            final int observerCount = mDiscoveryObservers.beginBroadcast();
            for (int i = 0; i < observerCount; i++) {
                IPrinterDiscoveryObserver observer = mDiscoveryObservers.getBroadcastItem(i);
                pw.append(prefix).append(prefix).append(observer.toString());
                pw.println();
            }
            mDiscoveryObservers.finishBroadcast();

            pw.append(prefix).append(tab).append("start discovery requests:").println();
            final int tokenCount = this.mStartedPrinterDiscoveryTokens.size();
            for (int i = 0; i < tokenCount; i++) {
                IBinder token = mStartedPrinterDiscoveryTokens.get(i);
                pw.append(prefix).append(tab).append(tab).append(token.toString()).println();
            }

            pw.append(prefix).append(tab).append("tracked printer requests:").println();
            final int trackedPrinters = mStateTrackedPrinters.size();
            for (int i = 0; i < trackedPrinters; i++) {
                PrinterId printer = mStateTrackedPrinters.get(i);
                pw.append(prefix).append(tab).append(tab).append(printer.toString()).println();
            }

            pw.append(prefix).append(tab).append("printers:").println();
            final int pritnerCount = mPrinters.size();
            for (int i = 0; i < pritnerCount; i++) {
                PrinterInfo printer = mPrinters.valueAt(i);
                pw.append(prefix).append(tab).append(tab).append(
                        printer.toString()).println();
            }
        }

        private void removePrintersForServiceLocked(ComponentName serviceName) {
            // No printers - nothing to do.
            if (mPrinters.isEmpty()) {
                return;
            }
            // Remove the printers for that service.
            List<PrinterId> removedPrinterIds = null;
            final int printerCount = mPrinters.size();
            for (int i = 0; i < printerCount; i++) {
                PrinterId printerId = mPrinters.keyAt(i);
                if (printerId.getServiceName().equals(serviceName)) {
                    if (removedPrinterIds == null) {
                        removedPrinterIds = new ArrayList<PrinterId>();
                    }
                    removedPrinterIds.add(printerId);
                }
            }
            if (removedPrinterIds != null) {
                final int removedPrinterCount = removedPrinterIds.size();
                for (int i = 0; i < removedPrinterCount; i++) {
                    mPrinters.remove(removedPrinterIds.get(i));
                }
                mSessionHandler.obtainMessage(
                        SessionHandler.MSG_DISPATCH_PRINTERS_REMOVED,
                        removedPrinterIds).sendToTarget();
            }
        }

        private void handleDispatchPrintersAdded(List<PrinterInfo> addedPrinters) {
            final int observerCount = mDiscoveryObservers.beginBroadcast();
            for (int i = 0; i < observerCount; i++) {
                IPrinterDiscoveryObserver observer = mDiscoveryObservers.getBroadcastItem(i);
                handlePrintersAdded(observer, addedPrinters);
            }
            mDiscoveryObservers.finishBroadcast();
        }

        private void handleDispatchPrintersRemoved(List<PrinterId> removedPrinterIds) {
            final int observerCount = mDiscoveryObservers.beginBroadcast();
            for (int i = 0; i < observerCount; i++) {
                IPrinterDiscoveryObserver observer = mDiscoveryObservers.getBroadcastItem(i);
                handlePrintersRemoved(observer, removedPrinterIds);
            }
            mDiscoveryObservers.finishBroadcast();
        }

        private void handleDispatchCreatePrinterDiscoverySession(
                List<RemotePrintService> services) {
            final int serviceCount = services.size();
            for (int i = 0; i < serviceCount; i++) {
                RemotePrintService service = services.get(i);
                service.createPrinterDiscoverySession();
            }
        }

        private void handleDispatchDestroyPrinterDiscoverySession(
                List<RemotePrintService> services) {
            final int serviceCount = services.size();
            for (int i = 0; i < serviceCount; i++) {
                RemotePrintService service = services.get(i);
                service.destroyPrinterDiscoverySession();
            }
            onDestroyed();
        }

        private void handleDispatchStartPrinterDiscovery(
                List<RemotePrintService> services, List<PrinterId> printerIds) {
            final int serviceCount = services.size();
            for (int i = 0; i < serviceCount; i++) {
                RemotePrintService service = services.get(i);
                service.startPrinterDiscovery(printerIds);
            }
        }

        private void handleDispatchStopPrinterDiscovery(List<RemotePrintService> services) {
            final int serviceCount = services.size();
            for (int i = 0; i < serviceCount; i++) {
                RemotePrintService service = services.get(i);
                service.stopPrinterDiscovery();
            }
        }

        private void handleValidatePrinters(RemotePrintService service,
                List<PrinterId> printerIds) {
            service.validatePrinters(printerIds);
        }

        private void handleStartPrinterStateTracking(@NonNull RemotePrintService service,
                @NonNull PrinterId printerId) {
            service.startPrinterStateTracking(printerId);
        }

        private void handleStopPrinterStateTracking(RemotePrintService service,
                PrinterId printerId) {
            service.stopPrinterStateTracking(printerId);
        }

        private void handlePrintersAdded(IPrinterDiscoveryObserver observer,
            List<PrinterInfo> printers) {
            try {
                observer.onPrintersAdded(new ParceledListSlice<PrinterInfo>(printers));
            } catch (RemoteException re) {
                Log.e(LOG_TAG, "Error sending added printers", re);
            }
        }

        private void handlePrintersRemoved(IPrinterDiscoveryObserver observer,
            List<PrinterId> printerIds) {
            try {
                observer.onPrintersRemoved(new ParceledListSlice<PrinterId>(printerIds));
            } catch (RemoteException re) {
                Log.e(LOG_TAG, "Error sending removed printers", re);
            }
        }

        private final class SessionHandler extends Handler {
            public static final int MSG_PRINTERS_ADDED = 1;
            public static final int MSG_PRINTERS_REMOVED = 2;
            public static final int MSG_DISPATCH_PRINTERS_ADDED = 3;
            public static final int MSG_DISPATCH_PRINTERS_REMOVED = 4;

            public static final int MSG_CREATE_PRINTER_DISCOVERY_SESSION = 5;
            public static final int MSG_DESTROY_PRINTER_DISCOVERY_SESSION = 6;
            public static final int MSG_START_PRINTER_DISCOVERY = 7;
            public static final int MSG_STOP_PRINTER_DISCOVERY = 8;
            public static final int MSG_DISPATCH_CREATE_PRINTER_DISCOVERY_SESSION = 9;
            public static final int MSG_DISPATCH_DESTROY_PRINTER_DISCOVERY_SESSION = 10;
            public static final int MSG_DISPATCH_START_PRINTER_DISCOVERY = 11;
            public static final int MSG_DISPATCH_STOP_PRINTER_DISCOVERY = 12;
            public static final int MSG_VALIDATE_PRINTERS = 13;
            public static final int MSG_START_PRINTER_STATE_TRACKING = 14;
            public static final int MSG_STOP_PRINTER_STATE_TRACKING = 15;
            public static final int MSG_DESTROY_SERVICE = 16;

            SessionHandler(Looper looper) {
                super(looper, null, false);
            }

            @Override
            @SuppressWarnings("unchecked")
            public void handleMessage(Message message) {
                switch (message.what) {
                    case MSG_PRINTERS_ADDED: {
                        SomeArgs args = (SomeArgs) message.obj;
                        IPrinterDiscoveryObserver observer = (IPrinterDiscoveryObserver) args.arg1;
                        List<PrinterInfo> addedPrinters = (List<PrinterInfo>) args.arg2;
                        args.recycle();
                        handlePrintersAdded(observer, addedPrinters);
                    } break;

                    case MSG_PRINTERS_REMOVED: {
                        SomeArgs args = (SomeArgs) message.obj;
                        IPrinterDiscoveryObserver observer = (IPrinterDiscoveryObserver) args.arg1;
                        List<PrinterId> removedPrinterIds = (List<PrinterId>) args.arg2;
                        args.recycle();
                        handlePrintersRemoved(observer, removedPrinterIds);
                    }

                    case MSG_DISPATCH_PRINTERS_ADDED: {
                        List<PrinterInfo> addedPrinters = (List<PrinterInfo>) message.obj;
                        handleDispatchPrintersAdded(addedPrinters);
                    } break;

                    case MSG_DISPATCH_PRINTERS_REMOVED: {
                        List<PrinterId> removedPrinterIds = (List<PrinterId>) message.obj;
                        handleDispatchPrintersRemoved(removedPrinterIds);
                    } break;

                    case MSG_CREATE_PRINTER_DISCOVERY_SESSION: {
                        RemotePrintService service = (RemotePrintService) message.obj;
                        service.createPrinterDiscoverySession();
                    } break;

                    case MSG_DESTROY_PRINTER_DISCOVERY_SESSION: {
                        RemotePrintService service = (RemotePrintService) message.obj;
                        service.destroyPrinterDiscoverySession();
                    } break;

                    case MSG_START_PRINTER_DISCOVERY: {
                        RemotePrintService service = (RemotePrintService) message.obj;
                        service.startPrinterDiscovery(null);
                    } break;

                    case MSG_STOP_PRINTER_DISCOVERY: {
                        RemotePrintService service = (RemotePrintService) message.obj;
                        service.stopPrinterDiscovery();
                    } break;

                    case MSG_DISPATCH_CREATE_PRINTER_DISCOVERY_SESSION: {
                        List<RemotePrintService> services = (List<RemotePrintService>) message.obj;
                        handleDispatchCreatePrinterDiscoverySession(services);
                    } break;

                    case MSG_DISPATCH_DESTROY_PRINTER_DISCOVERY_SESSION: {
                        List<RemotePrintService> services = (List<RemotePrintService>) message.obj;
                        handleDispatchDestroyPrinterDiscoverySession(services);
                    } break;

                    case MSG_DISPATCH_START_PRINTER_DISCOVERY: {
                        SomeArgs args = (SomeArgs) message.obj;
                        List<RemotePrintService> services = (List<RemotePrintService>) args.arg1;
                        List<PrinterId> printerIds = (List<PrinterId>) args.arg2;
                        args.recycle();
                        handleDispatchStartPrinterDiscovery(services, printerIds);
                    } break;

                    case MSG_DISPATCH_STOP_PRINTER_DISCOVERY: {
                        List<RemotePrintService> services = (List<RemotePrintService>) message.obj;
                        handleDispatchStopPrinterDiscovery(services);
                    } break;

                    case MSG_VALIDATE_PRINTERS: {
                        SomeArgs args = (SomeArgs) message.obj;
                        RemotePrintService service = (RemotePrintService) args.arg1;
                        List<PrinterId> printerIds = (List<PrinterId>) args.arg2;
                        args.recycle();
                        handleValidatePrinters(service, printerIds);
                    } break;

                    case MSG_START_PRINTER_STATE_TRACKING: {
                        SomeArgs args = (SomeArgs) message.obj;
                        RemotePrintService service = (RemotePrintService) args.arg1;
                        PrinterId printerId = (PrinterId) args.arg2;
                        args.recycle();
                        handleStartPrinterStateTracking(service, printerId);
                    } break;

                    case MSG_STOP_PRINTER_STATE_TRACKING: {
                        SomeArgs args = (SomeArgs) message.obj;
                        RemotePrintService service = (RemotePrintService) args.arg1;
                        PrinterId printerId = (PrinterId) args.arg2;
                        args.recycle();
                        handleStopPrinterStateTracking(service, printerId);
                    } break;

                    case MSG_DESTROY_SERVICE: {
                        RemotePrintService service = (RemotePrintService) message.obj;
                        service.destroy();
                    } break;
                }
            }
        }
    }

    private final class PrintJobForAppCache {
        private final SparseArray<List<PrintJobInfo>> mPrintJobsForRunningApp =
                new SparseArray<List<PrintJobInfo>>();

        public boolean onPrintJobCreated(final IBinder creator, final int appId,
                PrintJobInfo printJob) {
            try {
                creator.linkToDeath(new DeathRecipient() {
                    @Override
                    public void binderDied() {
                        creator.unlinkToDeath(this, 0);
                        synchronized (mLock) {
                            mPrintJobsForRunningApp.remove(appId);
                        }
                    }
                }, 0);
            } catch (RemoteException re) {
                /* The process is already dead - we just failed. */
                return false;
            }
            synchronized (mLock) {
                List<PrintJobInfo> printJobsForApp = mPrintJobsForRunningApp.get(appId);
                if (printJobsForApp == null) {
                    printJobsForApp = new ArrayList<PrintJobInfo>();
                    mPrintJobsForRunningApp.put(appId, printJobsForApp);
                }
                printJobsForApp.add(printJob);
            }
            return true;
        }

        public void onPrintJobStateChanged(PrintJobInfo printJob) {
            synchronized (mLock) {
                List<PrintJobInfo> printJobsForApp = mPrintJobsForRunningApp.get(
                        printJob.getAppId());
                if (printJobsForApp == null) {
                    return;
                }
                final int printJobCount = printJobsForApp.size();
                for (int i = 0; i < printJobCount; i++) {
                    PrintJobInfo oldPrintJob = printJobsForApp.get(i);
                    if (oldPrintJob.getId().equals(printJob.getId())) {
                        printJobsForApp.set(i, printJob);
                    }
                }
            }
        }

        public PrintJobInfo getPrintJob(PrintJobId printJobId, int appId) {
            synchronized (mLock) {
                List<PrintJobInfo> printJobsForApp = mPrintJobsForRunningApp.get(appId);
                if (printJobsForApp == null) {
                    return null;
                }
                final int printJobCount = printJobsForApp.size();
                for (int i = 0; i < printJobCount; i++) {
                    PrintJobInfo printJob = printJobsForApp.get(i);
                    if (printJob.getId().equals(printJobId)) {
                        return printJob;
                    }
                }
            }
            return null;
        }

        public List<PrintJobInfo> getPrintJobs(int appId) {
            synchronized (mLock) {
                List<PrintJobInfo> printJobs = null;
                if (appId == PrintManager.APP_ID_ANY) {
                    final int bucketCount = mPrintJobsForRunningApp.size();
                    for (int i = 0; i < bucketCount; i++) {
                        List<PrintJobInfo> bucket = mPrintJobsForRunningApp.valueAt(i);
                        if (printJobs == null) {
                            printJobs = new ArrayList<PrintJobInfo>();
                        }
                        printJobs.addAll(bucket);
                    }
                } else {
                    List<PrintJobInfo> bucket = mPrintJobsForRunningApp.get(appId);
                    if (bucket != null) {
                        if (printJobs == null) {
                            printJobs = new ArrayList<PrintJobInfo>();
                        }
                        printJobs.addAll(bucket);
                    }
                }
                if (printJobs != null) {
                    return printJobs;
                }
                return Collections.emptyList();
            }
        }

        public void dump(PrintWriter pw, String prefix) {
            synchronized (mLock) {
                String tab = "  ";
                final int bucketCount = mPrintJobsForRunningApp.size();
                for (int i = 0; i < bucketCount; i++) {
                    final int appId = mPrintJobsForRunningApp.keyAt(i);
                    pw.append(prefix).append("appId=" + appId).append(':').println();
                    List<PrintJobInfo> bucket = mPrintJobsForRunningApp.valueAt(i);
                    final int printJobCount = bucket.size();
                    for (int j = 0; j < printJobCount; j++) {
                        PrintJobInfo printJob = bucket.get(j);
                        pw.append(prefix).append(tab).append(printJob.toString()).println();
                    }
                }
            }
        }
    }
}
