/*
 * 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 com.android.internal.print.DumpUtils.writePrinterId;
import static com.android.internal.util.dump.DumpUtils.writeComponentName;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;

import android.annotation.FloatRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ParceledListSlice;
import android.graphics.drawable.Icon;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.UserHandle;
import android.print.PrintJobId;
import android.print.PrintJobInfo;
import android.print.PrintManager;
import android.print.PrinterId;
import android.print.PrinterInfo;
import android.printservice.IPrintService;
import android.printservice.IPrintServiceClient;
import android.service.print.ActivePrintServiceProto;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.dump.DualDumpOutputStream;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

/**
 * This class represents a remote print service. It abstracts away the binding
 * and unbinding from the remote implementation. Clients can call methods of
 * this class without worrying about when and how to bind/unbind.
 */
final class RemotePrintService implements DeathRecipient {

    private static final String LOG_TAG = "RemotePrintService";

    private static final boolean DEBUG = false;

    private final Object mLock = new Object();

    private final Context mContext;

    private final ComponentName mComponentName;

    private final Intent mIntent;

    private final RemotePrintSpooler mSpooler;

    private final PrintServiceCallbacks mCallbacks;

    private final int mUserId;

    private final List<Runnable> mPendingCommands = new ArrayList<Runnable>();

    private final ServiceConnection mServiceConnection = new RemoteServiceConneciton();

    private final RemotePrintServiceClient mPrintServiceClient;

    private IPrintService mPrintService;

    private boolean mBinding;

    private boolean mDestroyed;

    private boolean mHasActivePrintJobs;

    private boolean mHasPrinterDiscoverySession;

    private boolean mServiceDied;

    private List<PrinterId> mDiscoveryPriorityList;

    @GuardedBy("mLock")
    private List<PrinterId> mTrackedPrinterList;

    public static interface PrintServiceCallbacks {
        public void onPrintersAdded(List<PrinterInfo> printers);
        public void onPrintersRemoved(List<PrinterId> printerIds);
        public void onServiceDied(RemotePrintService service);

        /**
         * Handle that a custom icon for a printer was loaded.
         *
         * @param printerId the id of the printer the icon belongs to
         * @param icon the icon that was loaded
         * @see android.print.PrinterInfo.Builder#setHasCustomPrinterIcon()
         */
        public void onCustomPrinterIconLoaded(PrinterId printerId, Icon icon);
    }

    public RemotePrintService(Context context, ComponentName componentName, int userId,
            RemotePrintSpooler spooler, PrintServiceCallbacks callbacks) {
        mContext = context;
        mCallbacks = callbacks;
        mComponentName = componentName;
        mIntent = new Intent().setComponent(mComponentName);
        mUserId = userId;
        mSpooler = spooler;
        mPrintServiceClient = new RemotePrintServiceClient(this);
    }

    public ComponentName getComponentName() {
        return mComponentName;
    }

    public void destroy() {
        Handler.getMain().sendMessage(obtainMessage(
                RemotePrintService::handleDestroy, this));
    }

    private void handleDestroy() {
        // Stop tracking printers.
        stopTrackingAllPrinters();

        // Stop printer discovery.
        if (mDiscoveryPriorityList != null) {
            handleStopPrinterDiscovery();
        }

        // Destroy the discovery session.
        if (mHasPrinterDiscoverySession) {
            handleDestroyPrinterDiscoverySession();
        }

        // Unbind.
        ensureUnbound();

        // Done
        mDestroyed = true;
    }

    @Override
    public void binderDied() {
        Handler.getMain().sendMessage(obtainMessage(
                RemotePrintService::handleBinderDied, this));
    }

    private void handleBinderDied() {
        if (mPrintService != null) {
            mPrintService.asBinder().unlinkToDeath(this, 0);
        }

        mPrintService = null;
        mServiceDied = true;
        mCallbacks.onServiceDied(this);
    }

    public void onAllPrintJobsHandled() {
        Handler.getMain().sendMessage(obtainMessage(
                RemotePrintService::handleOnAllPrintJobsHandled, this));
    }

    private void handleOnAllPrintJobsHandled() {
        mHasActivePrintJobs = false;
        if (!isBound()) {
            // The service is dead and neither has active jobs nor discovery
            // session, so ensure we are unbound since the service has no work.
            if (mServiceDied && !mHasPrinterDiscoverySession) {
                ensureUnbound();
                return;
            }
            ensureBound();
            mPendingCommands.add(new Runnable() {
                @Override
                public void run() {
                    handleOnAllPrintJobsHandled();
                }
            });
        } else {
            if (DEBUG) {
                Slog.i(LOG_TAG, "[user: " + mUserId + "] onAllPrintJobsHandled()");
            }
            // If the service has a printer discovery session
            // created we should not disconnect from it just yet.
            if (!mHasPrinterDiscoverySession) {
                ensureUnbound();
            }
        }
    }

    public void onRequestCancelPrintJob(PrintJobInfo printJob) {
        Handler.getMain().sendMessage(obtainMessage(
                RemotePrintService::handleRequestCancelPrintJob, this, printJob));
    }

    private void handleRequestCancelPrintJob(final PrintJobInfo printJob) {
        if (!isBound()) {
            ensureBound();
            mPendingCommands.add(new Runnable() {
                @Override
                public void run() {
                    handleRequestCancelPrintJob(printJob);
                }
            });
        } else {
            if (DEBUG) {
                Slog.i(LOG_TAG, "[user: " + mUserId + "] requestCancelPrintJob()");
            }
            try {
                mPrintService.requestCancelPrintJob(printJob);
            } catch (RemoteException re) {
                Slog.e(LOG_TAG, "Error canceling a pring job.", re);
            }
        }
    }

    public void onPrintJobQueued(PrintJobInfo printJob) {
        Handler.getMain().sendMessage(obtainMessage(
                RemotePrintService::handleOnPrintJobQueued, this, printJob));
    }

    private void handleOnPrintJobQueued(final PrintJobInfo printJob) {
        mHasActivePrintJobs = true;
        if (!isBound()) {
            ensureBound();
            mPendingCommands.add(new Runnable() {
                @Override
                public void run() {
                    handleOnPrintJobQueued(printJob);
                }
            });
        } else {
            if (DEBUG) {
                Slog.i(LOG_TAG, "[user: " + mUserId + "] onPrintJobQueued()");
            }
            try {
                mPrintService.onPrintJobQueued(printJob);
            } catch (RemoteException re) {
                Slog.e(LOG_TAG, "Error announcing queued pring job.", re);
            }
        }
    }

    public void createPrinterDiscoverySession() {
        Handler.getMain().sendMessage(obtainMessage(
                RemotePrintService::handleCreatePrinterDiscoverySession, this));
    }

    private void handleCreatePrinterDiscoverySession() {
        mHasPrinterDiscoverySession = true;
        if (!isBound()) {
            ensureBound();
            mPendingCommands.add(new Runnable() {
                @Override
                public void run() {
                    handleCreatePrinterDiscoverySession();
                }
            });
        } else {
            if (DEBUG) {
                Slog.i(LOG_TAG, "[user: " + mUserId + "] createPrinterDiscoverySession()");
            }
            try {
                mPrintService.createPrinterDiscoverySession();
            } catch (RemoteException re) {
                Slog.e(LOG_TAG, "Error creating printer discovery session.", re);
            }
        }
    }

    public void destroyPrinterDiscoverySession() {
        Handler.getMain().sendMessage(obtainMessage(
                RemotePrintService::handleDestroyPrinterDiscoverySession, this));
    }

    private void handleDestroyPrinterDiscoverySession() {
        mHasPrinterDiscoverySession = false;
        if (!isBound()) {
            // The service is dead and neither has active jobs nor discovery
            // session, so ensure we are unbound since the service has no work.
            if (mServiceDied && !mHasActivePrintJobs) {
                ensureUnbound();
                return;
            }
            ensureBound();
            mPendingCommands.add(new Runnable() {
                @Override
                public void run() {
                    handleDestroyPrinterDiscoverySession();
                }
            });
        } else {
            if (DEBUG) {
                Slog.i(LOG_TAG, "[user: " + mUserId + "] destroyPrinterDiscoverySession()");
            }
            try {
                mPrintService.destroyPrinterDiscoverySession();
            } catch (RemoteException re) {
                Slog.e(LOG_TAG, "Error destroying printer dicovery session.", re);
            }
            // If the service has no print jobs and no active discovery
            // session anymore we should disconnect from it.
            if (!mHasActivePrintJobs) {
                ensureUnbound();
            }
        }
    }

    public void startPrinterDiscovery(List<PrinterId> priorityList) {
        Handler.getMain().sendMessage(obtainMessage(
                RemotePrintService::handleStartPrinterDiscovery, this, priorityList));
    }

    private void handleStartPrinterDiscovery(final List<PrinterId> priorityList) {
        // Take a note that we are doing discovery.
        mDiscoveryPriorityList = new ArrayList<PrinterId>();
        if (priorityList != null) {
            mDiscoveryPriorityList.addAll(priorityList);
        }
        if (!isBound()) {
            ensureBound();
            mPendingCommands.add(new Runnable() {
                @Override
                public void run() {
                    handleStartPrinterDiscovery(priorityList);
                }
            });
        } else {
            if (DEBUG) {
                Slog.i(LOG_TAG, "[user: " + mUserId + "] startPrinterDiscovery()");
            }
            try {
                mPrintService.startPrinterDiscovery(priorityList);
            } catch (RemoteException re) {
                Slog.e(LOG_TAG, "Error starting printer dicovery.", re);
            }
        }
    }

    public void stopPrinterDiscovery() {
        Handler.getMain().sendMessage(obtainMessage(
                RemotePrintService::handleStopPrinterDiscovery, this));
    }

    private void handleStopPrinterDiscovery() {
        // We are not doing discovery anymore.
        mDiscoveryPriorityList = null;
        if (!isBound()) {
            ensureBound();
            mPendingCommands.add(new Runnable() {
                @Override
                public void run() {
                    handleStopPrinterDiscovery();
                }
            });
        } else {
            if (DEBUG) {
                Slog.i(LOG_TAG, "[user: " + mUserId + "] stopPrinterDiscovery()");
            }

            // Stop tracking printers.
            stopTrackingAllPrinters();

            try {
                mPrintService.stopPrinterDiscovery();
            } catch (RemoteException re) {
                Slog.e(LOG_TAG, "Error stopping printer discovery.", re);
            }
        }
    }

    public void validatePrinters(List<PrinterId> printerIds) {
        Handler.getMain().sendMessage(obtainMessage(
                RemotePrintService::handleValidatePrinters, this, printerIds));
    }

    private void handleValidatePrinters(final List<PrinterId> printerIds) {
        if (!isBound()) {
            ensureBound();
            mPendingCommands.add(new Runnable() {
                @Override
                public void run() {
                    handleValidatePrinters(printerIds);
                }
            });
        } else {
            if (DEBUG) {
                Slog.i(LOG_TAG, "[user: " + mUserId + "] validatePrinters()");
            }
            try {
                mPrintService.validatePrinters(printerIds);
            } catch (RemoteException re) {
                Slog.e(LOG_TAG, "Error requesting printers validation.", re);
            }
        }
    }

    public void startPrinterStateTracking(@NonNull PrinterId printerId) {
        Handler.getMain().sendMessage(obtainMessage(
                RemotePrintService::handleStartPrinterStateTracking, this, printerId));
    }

    /**
     * Queue a request for a custom printer icon for a printer.
     *
     * @param printerId the id of the printer the icon should be loaded for
     * @see android.print.PrinterInfo.Builder#setHasCustomPrinterIcon
     */
    public void requestCustomPrinterIcon(@NonNull PrinterId printerId) {
        Handler.getMain().sendMessage(obtainMessage(
                RemotePrintService::handleRequestCustomPrinterIcon, this, printerId));
    }

    /**
     * Request a custom printer icon for a printer.
     *
     * @param printerId the id of the printer the icon should be loaded for
     * @see android.print.PrinterInfo.Builder#setHasCustomPrinterIcon
     */
    private void handleRequestCustomPrinterIcon(@NonNull PrinterId printerId) {
        if (!isBound()) {
            ensureBound();
            mPendingCommands.add(() -> handleRequestCustomPrinterIcon(printerId));
        } else {
            if (DEBUG) {
                Slog.i(LOG_TAG, "[user: " + mUserId + "] requestCustomPrinterIcon()");
            }

            try {
                mPrintService.requestCustomPrinterIcon(printerId);
            } catch (RemoteException re) {
                Slog.e(LOG_TAG, "Error requesting icon for " + printerId, re);
            }
        }
    }

    private void handleStartPrinterStateTracking(final @NonNull PrinterId printerId) {
        synchronized (mLock) {
            // Take a note we are tracking the printer.
            if (mTrackedPrinterList == null) {
                mTrackedPrinterList = new ArrayList<PrinterId>();
            }
            mTrackedPrinterList.add(printerId);
        }

        if (!isBound()) {
            ensureBound();
            mPendingCommands.add(new Runnable() {
                @Override
                public void run() {
                    handleStartPrinterStateTracking(printerId);
                }
            });
        } else {
            if (DEBUG) {
                Slog.i(LOG_TAG, "[user: " + mUserId + "] startPrinterTracking()");
            }
            try {
                mPrintService.startPrinterStateTracking(printerId);
            } catch (RemoteException re) {
                Slog.e(LOG_TAG, "Error requesting start printer tracking.", re);
            }
        }
    }

    public void stopPrinterStateTracking(PrinterId printerId) {
        Handler.getMain().sendMessage(obtainMessage(
                RemotePrintService::handleStopPrinterStateTracking, this, printerId));
    }

    private void handleStopPrinterStateTracking(final PrinterId printerId) {
        synchronized (mLock) {
            // We are no longer tracking the printer.
            if (mTrackedPrinterList == null || !mTrackedPrinterList.remove(printerId)) {
                return;
            }
            if (mTrackedPrinterList.isEmpty()) {
                mTrackedPrinterList = null;
            }
        }

        if (!isBound()) {
            ensureBound();
            mPendingCommands.add(new Runnable() {
                @Override
                public void run() {
                    handleStopPrinterStateTracking(printerId);
                }
            });
        } else {
            if (DEBUG) {
                Slog.i(LOG_TAG, "[user: " + mUserId + "] stopPrinterTracking()");
            }
            try {
                mPrintService.stopPrinterStateTracking(printerId);
            } catch (RemoteException re) {
                Slog.e(LOG_TAG, "Error requesting stop printer tracking.", re);
            }
        }
    }

    private void stopTrackingAllPrinters() {
        synchronized (mLock) {
            if (mTrackedPrinterList == null) {
                return;
            }
            final int trackedPrinterCount = mTrackedPrinterList.size();
            for (int i = trackedPrinterCount - 1; i >= 0; i--) {
                PrinterId printerId = mTrackedPrinterList.get(i);
                if (printerId.getServiceName().equals(mComponentName)) {
                    handleStopPrinterStateTracking(printerId);
                }
            }
        }
    }

    public void dump(@NonNull DualDumpOutputStream proto) {
        writeComponentName(proto, "component_name", ActivePrintServiceProto.COMPONENT_NAME,
                mComponentName);

        proto.write("is_destroyed", ActivePrintServiceProto.IS_DESTROYED, mDestroyed);
        proto.write("is_bound", ActivePrintServiceProto.IS_BOUND, isBound());
        proto.write("has_discovery_session", ActivePrintServiceProto.HAS_DISCOVERY_SESSION,
                mHasPrinterDiscoverySession);
        proto.write("has_active_print_jobs", ActivePrintServiceProto.HAS_ACTIVE_PRINT_JOBS,
                mHasActivePrintJobs);
        proto.write("is_discovering_printers", ActivePrintServiceProto.IS_DISCOVERING_PRINTERS,
                mDiscoveryPriorityList != null);

        synchronized (mLock) {
            if (mTrackedPrinterList != null) {
                int numTrackedPrinters = mTrackedPrinterList.size();
                for (int i = 0; i < numTrackedPrinters; i++) {
                    writePrinterId(proto, "tracked_printers",
                            ActivePrintServiceProto.TRACKED_PRINTERS, mTrackedPrinterList.get(i));
                }
            }
        }
    }

    private boolean isBound() {
        return mPrintService != null;
    }

    private void ensureBound() {
        if (isBound() || mBinding) {
            return;
        }
        if (DEBUG) {
            Slog.i(LOG_TAG, "[user: " + mUserId + "] ensureBound()");
        }
        mBinding = true;

        boolean wasBound = mContext.bindServiceAsUser(mIntent, mServiceConnection,
                Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
                        | Context.BIND_INCLUDE_CAPABILITIES | Context.BIND_ALLOW_INSTANT,
                new UserHandle(mUserId));

        if (!wasBound) {
            if (DEBUG) {
                Slog.i(LOG_TAG, "[user: " + mUserId + "] could not bind to " + mIntent);
            }
            mBinding = false;

            if (!mServiceDied) {
                handleBinderDied();
            }
        }
    }

    private void ensureUnbound() {
        if (!isBound() && !mBinding) {
            return;
        }
        if (DEBUG) {
            Slog.i(LOG_TAG, "[user: " + mUserId + "] ensureUnbound()");
        }
        mBinding = false;
        mPendingCommands.clear();
        mHasActivePrintJobs = false;
        mHasPrinterDiscoverySession = false;
        mDiscoveryPriorityList = null;

        synchronized (mLock) {
            mTrackedPrinterList = null;
        }

        if (isBound()) {
            try {
                mPrintService.setClient(null);
            } catch (RemoteException re) {
                /* ignore */
            }
            mPrintService.asBinder().unlinkToDeath(this, 0);
            mPrintService = null;
            mContext.unbindService(mServiceConnection);
        }
    }

    private class RemoteServiceConneciton implements ServiceConnection {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            if (mDestroyed || !mBinding) {
                mContext.unbindService(mServiceConnection);
                return;
            }
            mBinding = false;
            mPrintService = IPrintService.Stub.asInterface(service);
            try {
                service.linkToDeath(RemotePrintService.this, 0);
            } catch (RemoteException re) {
                handleBinderDied();
                return;
            }
            try {
                mPrintService.setClient(mPrintServiceClient);
            } catch (RemoteException re) {
                Slog.e(LOG_TAG, "Error setting client for: " + service, re);
                handleBinderDied();
                return;
            }
            // If the service died and there is a discovery session, recreate it.
            if (mServiceDied && mHasPrinterDiscoverySession) {
                handleCreatePrinterDiscoverySession();
            }
            // If the service died and there is discovery started, restart it.
            if (mServiceDied && mDiscoveryPriorityList != null) {
                handleStartPrinterDiscovery(mDiscoveryPriorityList);
            }
            synchronized (mLock) {
                // If the service died and printers were tracked, start tracking.
                if (mServiceDied && mTrackedPrinterList != null) {
                    final int trackedPrinterCount = mTrackedPrinterList.size();
                    for (int i = 0; i < trackedPrinterCount; i++) {
                        handleStartPrinterStateTracking(mTrackedPrinterList.get(i));
                    }
                }
            }
            // Finally, do all the pending work.
            while (!mPendingCommands.isEmpty()) {
                Runnable pendingCommand = mPendingCommands.remove(0);
                pendingCommand.run();
            }
            // We did a best effort to get to the last state if we crashed.
            // If we do not have print jobs and no discovery is in progress,
            // then no need to be bound.
            if (!mHasPrinterDiscoverySession && !mHasActivePrintJobs) {
                ensureUnbound();
            }
            mServiceDied = false;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mBinding = true;
        }
    }

    private static final class RemotePrintServiceClient extends IPrintServiceClient.Stub {
        private final WeakReference<RemotePrintService> mWeakService;

        public RemotePrintServiceClient(RemotePrintService service) {
            mWeakService = new WeakReference<RemotePrintService>(service);
        }

        @Override
        public List<PrintJobInfo> getPrintJobInfos() {
            RemotePrintService service = mWeakService.get();
            if (service != null) {
                final long identity = Binder.clearCallingIdentity();
                try {
                    return service.mSpooler.getPrintJobInfos(service.mComponentName,
                            PrintJobInfo.STATE_ANY_SCHEDULED, PrintManager.APP_ID_ANY);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
            return null;
        }

        @Override
        public PrintJobInfo getPrintJobInfo(PrintJobId printJobId) {
            RemotePrintService service = mWeakService.get();
            if (service != null) {
                final long identity = Binder.clearCallingIdentity();
                try {
                    return service.mSpooler.getPrintJobInfo(printJobId,
                            PrintManager.APP_ID_ANY);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
            return null;
        }

        @Override
        public boolean setPrintJobState(PrintJobId printJobId, int state, String error) {
            RemotePrintService service = mWeakService.get();
            if (service != null) {
                final long identity = Binder.clearCallingIdentity();
                try {
                    return service.mSpooler.setPrintJobState(printJobId, state, error);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
            return false;
        }

        @Override
        public boolean setPrintJobTag(PrintJobId printJobId, String tag) {
            RemotePrintService service = mWeakService.get();
            if (service != null) {
                final long identity = Binder.clearCallingIdentity();
                try {
                    return service.mSpooler.setPrintJobTag(printJobId, tag);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
            return false;
        }

        @Override
        public void writePrintJobData(ParcelFileDescriptor fd, PrintJobId printJobId) {
            RemotePrintService service = mWeakService.get();
            if (service != null) {
                final long identity = Binder.clearCallingIdentity();
                try {
                    service.mSpooler.writePrintJobData(fd, printJobId);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
        }

        @Override
        public void setProgress(@NonNull PrintJobId printJobId,
                @FloatRange(from=0.0, to=1.0) float progress) {
            RemotePrintService service = mWeakService.get();
            if (service != null) {
                final long identity = Binder.clearCallingIdentity();
                try {
                    service.mSpooler.setProgress(printJobId, progress);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
        }

        @Override
        public void setStatus(@NonNull PrintJobId printJobId, @Nullable CharSequence status) {
            RemotePrintService service = mWeakService.get();
            if (service != null) {
                final long identity = Binder.clearCallingIdentity();
                try {
                    service.mSpooler.setStatus(printJobId, status);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
        }

        @Override
        public void setStatusRes(@NonNull PrintJobId printJobId, @StringRes int status,
                @NonNull CharSequence appPackageName) {
            RemotePrintService service = mWeakService.get();
            if (service != null) {
                final long identity = Binder.clearCallingIdentity();
                try {
                    service.mSpooler.setStatus(printJobId, status, appPackageName);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
        }

        @Override
        @SuppressWarnings({"rawtypes", "unchecked"})
        public void onPrintersAdded(ParceledListSlice printers) {
            RemotePrintService service = mWeakService.get();
            if (service != null) {
                List<PrinterInfo> addedPrinters = (List<PrinterInfo>) printers.getList();
                throwIfPrinterIdsForPrinterInfoTampered(service.mComponentName, addedPrinters);
                final long identity = Binder.clearCallingIdentity();
                try {
                    service.mCallbacks.onPrintersAdded(addedPrinters);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
        }

        @Override
        @SuppressWarnings({"rawtypes", "unchecked"})
        public void onPrintersRemoved(ParceledListSlice printerIds) {
            RemotePrintService service = mWeakService.get();
            if (service != null) {
                List<PrinterId> removedPrinterIds = (List<PrinterId>) printerIds.getList();
                throwIfPrinterIdsTampered(service.mComponentName, removedPrinterIds);
                final long identity = Binder.clearCallingIdentity();
                try {
                    service.mCallbacks.onPrintersRemoved(removedPrinterIds);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
        }

        private void throwIfPrinterIdsForPrinterInfoTampered(ComponentName serviceName,
                List<PrinterInfo> printerInfos) {
            final int printerInfoCount = printerInfos.size();
            for (int i = 0; i < printerInfoCount; i++) {
                PrinterId printerId = printerInfos.get(i).getId();
                throwIfPrinterIdTampered(serviceName, printerId);
            }
        }

        private void throwIfPrinterIdsTampered(ComponentName serviceName,
                List<PrinterId> printerIds) {
            final int printerIdCount = printerIds.size();
            for (int i = 0; i < printerIdCount; i++) {
                PrinterId printerId = printerIds.get(i);
                throwIfPrinterIdTampered(serviceName, printerId);
            }
        }

        private void throwIfPrinterIdTampered(ComponentName serviceName, PrinterId printerId) {
            if (printerId == null || !printerId.getServiceName().equals(serviceName)) {
                throw new IllegalArgumentException("Invalid printer id: " + printerId);
            }
        }

        @Override
        public void onCustomPrinterIconLoaded(PrinterId printerId, Icon icon)
                throws RemoteException {
            RemotePrintService service = mWeakService.get();
            if (service != null) {
                final long identity = Binder.clearCallingIdentity();
                try {
                    service.mCallbacks.onCustomPrinterIconLoaded(printerId, icon);
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
            }
        }
    }
}
