15778822d86b0337407514b9372562b86edfa91cdAndreas Huber/*
25778822d86b0337407514b9372562b86edfa91cdAndreas Huber * Copyright (C) 2013 The Android Open Source Project
35778822d86b0337407514b9372562b86edfa91cdAndreas Huber *
45778822d86b0337407514b9372562b86edfa91cdAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
55778822d86b0337407514b9372562b86edfa91cdAndreas Huber * you may not use this file except in compliance with the License.
65778822d86b0337407514b9372562b86edfa91cdAndreas Huber * You may obtain a copy of the License at
75778822d86b0337407514b9372562b86edfa91cdAndreas Huber *
85778822d86b0337407514b9372562b86edfa91cdAndreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
95778822d86b0337407514b9372562b86edfa91cdAndreas Huber *
105778822d86b0337407514b9372562b86edfa91cdAndreas Huber * Unless required by applicable law or agreed to in writing, software
115778822d86b0337407514b9372562b86edfa91cdAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
125778822d86b0337407514b9372562b86edfa91cdAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135778822d86b0337407514b9372562b86edfa91cdAndreas Huber * See the License for the specific language governing permissions and
145778822d86b0337407514b9372562b86edfa91cdAndreas Huber * limitations under the License.
155778822d86b0337407514b9372562b86edfa91cdAndreas Huber */
165778822d86b0337407514b9372562b86edfa91cdAndreas Huber
175778822d86b0337407514b9372562b86edfa91cdAndreas Huberpackage com.android.server.print;
185778822d86b0337407514b9372562b86edfa91cdAndreas Huber
195778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport static com.android.internal.print.DumpUtils.writePrinterId;
20fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnarimport static com.android.internal.util.dump.DumpUtils.writeComponentName;
215778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
225778822d86b0337407514b9372562b86edfa91cdAndreas Huber
235778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport android.annotation.FloatRange;
245778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport android.annotation.NonNull;
255778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport android.annotation.Nullable;
261a2952aee048ca7b1765e2bc09ebe9aeddaeafa3Mathias Agopianimport android.annotation.StringRes;
27ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huberimport android.content.ComponentName;
285778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport android.content.Context;
295778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport android.content.Intent;
305778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport android.content.ServiceConnection;
315b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huberimport android.content.pm.ParceledListSlice;
32ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huberimport android.graphics.drawable.Icon;
335778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport android.os.Binder;
347cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFaddenimport android.os.Handler;
356f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissenimport android.os.IBinder;
36e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huberimport android.os.IBinder.DeathRecipient;
375778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport android.os.ParcelFileDescriptor;
385778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport android.os.RemoteException;
395778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport android.os.UserHandle;
405778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport android.print.PrintJobId;
41e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huberimport android.print.PrintJobInfo;
42e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huberimport android.print.PrintManager;
435778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport android.print.PrinterId;
445778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport android.print.PrinterInfo;
455778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport android.printservice.IPrintService;
465778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport android.printservice.IPrintServiceClient;
475778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport android.service.print.ActivePrintServiceProto;
485778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport android.util.Slog;
495778822d86b0337407514b9372562b86edfa91cdAndreas Huber
505778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport com.android.internal.annotations.GuardedBy;
515778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport com.android.internal.util.dump.DualDumpOutputStream;
525778822d86b0337407514b9372562b86edfa91cdAndreas Huber
535778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport java.lang.ref.WeakReference;
545778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport java.util.ArrayList;
555778822d86b0337407514b9372562b86edfa91cdAndreas Huberimport java.util.List;
565778822d86b0337407514b9372562b86edfa91cdAndreas Huber
575778822d86b0337407514b9372562b86edfa91cdAndreas Huber/**
585778822d86b0337407514b9372562b86edfa91cdAndreas Huber * This class represents a remote print service. It abstracts away the binding
595778822d86b0337407514b9372562b86edfa91cdAndreas Huber * and unbinding from the remote implementation. Clients can call methods of
605778822d86b0337407514b9372562b86edfa91cdAndreas Huber * this class without worrying about when and how to bind/unbind.
615778822d86b0337407514b9372562b86edfa91cdAndreas Huber */
625778822d86b0337407514b9372562b86edfa91cdAndreas Huberfinal class RemotePrintService implements DeathRecipient {
635778822d86b0337407514b9372562b86edfa91cdAndreas Huber
645778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private static final String LOG_TAG = "RemotePrintService";
655778822d86b0337407514b9372562b86edfa91cdAndreas Huber
665778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private static final boolean DEBUG = false;
675778822d86b0337407514b9372562b86edfa91cdAndreas Huber
685778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private final Object mLock = new Object();
695778822d86b0337407514b9372562b86edfa91cdAndreas Huber
7092cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar    private final Context mContext;
717cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden
725778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private final ComponentName mComponentName;
735778822d86b0337407514b9372562b86edfa91cdAndreas Huber
745778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private final Intent mIntent;
755778822d86b0337407514b9372562b86edfa91cdAndreas Huber
765778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private final RemotePrintSpooler mSpooler;
776507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden
786507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden    private final PrintServiceCallbacks mCallbacks;
795778822d86b0337407514b9372562b86edfa91cdAndreas Huber
805778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private final int mUserId;
815778822d86b0337407514b9372562b86edfa91cdAndreas Huber
825778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private final List<Runnable> mPendingCommands = new ArrayList<Runnable>();
835778822d86b0337407514b9372562b86edfa91cdAndreas Huber
845778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private final ServiceConnection mServiceConnection = new RemoteServiceConneciton();
855778822d86b0337407514b9372562b86edfa91cdAndreas Huber
865778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private final RemotePrintServiceClient mPrintServiceClient;
875778822d86b0337407514b9372562b86edfa91cdAndreas Huber
885778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private IPrintService mPrintService;
895778822d86b0337407514b9372562b86edfa91cdAndreas Huber
905778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private boolean mBinding;
915778822d86b0337407514b9372562b86edfa91cdAndreas Huber
925778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private boolean mDestroyed;
935778822d86b0337407514b9372562b86edfa91cdAndreas Huber
945778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private boolean mHasActivePrintJobs;
955778822d86b0337407514b9372562b86edfa91cdAndreas Huber
965778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private boolean mHasPrinterDiscoverySession;
975778822d86b0337407514b9372562b86edfa91cdAndreas Huber
985778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private boolean mServiceDied;
995778822d86b0337407514b9372562b86edfa91cdAndreas Huber
1005778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private List<PrinterId> mDiscoveryPriorityList;
1015778822d86b0337407514b9372562b86edfa91cdAndreas Huber
1025778822d86b0337407514b9372562b86edfa91cdAndreas Huber    @GuardedBy("mLock")
1035778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private List<PrinterId> mTrackedPrinterList;
1045778822d86b0337407514b9372562b86edfa91cdAndreas Huber
1055778822d86b0337407514b9372562b86edfa91cdAndreas Huber    public static interface PrintServiceCallbacks {
10692cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar        public void onPrintersAdded(List<PrinterInfo> printers);
1075778822d86b0337407514b9372562b86edfa91cdAndreas Huber        public void onPrintersRemoved(List<PrinterId> printerIds);
1085778822d86b0337407514b9372562b86edfa91cdAndreas Huber        public void onServiceDied(RemotePrintService service);
1095778822d86b0337407514b9372562b86edfa91cdAndreas Huber
1106f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen        /**
1116f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen         * Handle that a custom icon for a printer was loaded.
1126f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen         *
1136f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen         * @param printerId the id of the printer the icon belongs to
1146f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen         * @param icon the icon that was loaded
1156f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen         * @see android.print.PrinterInfo.Builder#setHasCustomPrinterIcon()
1166f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen         */
1176f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen        public void onCustomPrinterIconLoaded(PrinterId printerId, Icon icon);
1186f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen    }
1196f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen
12084333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber    public RemotePrintService(Context context, ComponentName componentName, int userId,
1216f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen            RemotePrintSpooler spooler, PrintServiceCallbacks callbacks) {
1226f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen        mContext = context;
1236f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen        mCallbacks = callbacks;
1246f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen        mComponentName = componentName;
1256f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen        mIntent = new Intent().setComponent(mComponentName);
1266f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen        mUserId = userId;
1276f9439efd2a6004b588605f6a9d4af20c98e8e80Marco Nelissen        mSpooler = spooler;
1285778822d86b0337407514b9372562b86edfa91cdAndreas Huber        mPrintServiceClient = new RemotePrintServiceClient(this);
1295778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
1305778822d86b0337407514b9372562b86edfa91cdAndreas Huber
1315778822d86b0337407514b9372562b86edfa91cdAndreas Huber    public ComponentName getComponentName() {
1325778822d86b0337407514b9372562b86edfa91cdAndreas Huber        return mComponentName;
1335778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
1345778822d86b0337407514b9372562b86edfa91cdAndreas Huber
1355778822d86b0337407514b9372562b86edfa91cdAndreas Huber    public void destroy() {
1365778822d86b0337407514b9372562b86edfa91cdAndreas Huber        Handler.getMain().sendMessage(obtainMessage(
1375778822d86b0337407514b9372562b86edfa91cdAndreas Huber                RemotePrintService::handleDestroy, this));
1385778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
1395778822d86b0337407514b9372562b86edfa91cdAndreas Huber
1405778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private void handleDestroy() {
1415778822d86b0337407514b9372562b86edfa91cdAndreas Huber        // Stop tracking printers.
1425778822d86b0337407514b9372562b86edfa91cdAndreas Huber        stopTrackingAllPrinters();
1435778822d86b0337407514b9372562b86edfa91cdAndreas Huber
1445778822d86b0337407514b9372562b86edfa91cdAndreas Huber        // Stop printer discovery.
1455778822d86b0337407514b9372562b86edfa91cdAndreas Huber        if (mDiscoveryPriorityList != null) {
1465778822d86b0337407514b9372562b86edfa91cdAndreas Huber            handleStopPrinterDiscovery();
1475778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
1485778822d86b0337407514b9372562b86edfa91cdAndreas Huber
1495778822d86b0337407514b9372562b86edfa91cdAndreas Huber        // Destroy the discovery session.
1505778822d86b0337407514b9372562b86edfa91cdAndreas Huber        if (mHasPrinterDiscoverySession) {
1515778822d86b0337407514b9372562b86edfa91cdAndreas Huber            handleDestroyPrinterDiscoverySession();
1525778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
1535778822d86b0337407514b9372562b86edfa91cdAndreas Huber
1545778822d86b0337407514b9372562b86edfa91cdAndreas Huber        // Unbind.
1555778822d86b0337407514b9372562b86edfa91cdAndreas Huber        ensureUnbound();
1565778822d86b0337407514b9372562b86edfa91cdAndreas Huber
1575778822d86b0337407514b9372562b86edfa91cdAndreas Huber        // Done
1585778822d86b0337407514b9372562b86edfa91cdAndreas Huber        mDestroyed = true;
1595778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
1601a2952aee048ca7b1765e2bc09ebe9aeddaeafa3Mathias Agopian
1611bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    @Override
1625778822d86b0337407514b9372562b86edfa91cdAndreas Huber    public void binderDied() {
1635778822d86b0337407514b9372562b86edfa91cdAndreas Huber        Handler.getMain().sendMessage(obtainMessage(
1645778822d86b0337407514b9372562b86edfa91cdAndreas Huber                RemotePrintService::handleBinderDied, this));
1655778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
1665778822d86b0337407514b9372562b86edfa91cdAndreas Huber
1675778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private void handleBinderDied() {
1685778822d86b0337407514b9372562b86edfa91cdAndreas Huber        if (mPrintService != null) {
1691bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            mPrintService.asBinder().unlinkToDeath(this, 0);
1701bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        }
1711bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
1721bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        mPrintService = null;
1731bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        mServiceDied = true;
1741bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        mCallbacks.onServiceDied(this);
1751bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber    }
1765778822d86b0337407514b9372562b86edfa91cdAndreas Huber
1775778822d86b0337407514b9372562b86edfa91cdAndreas Huber    public void onAllPrintJobsHandled() {
1785778822d86b0337407514b9372562b86edfa91cdAndreas Huber        Handler.getMain().sendMessage(obtainMessage(
1795778822d86b0337407514b9372562b86edfa91cdAndreas Huber                RemotePrintService::handleOnAllPrintJobsHandled, this));
1805778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
1815778822d86b0337407514b9372562b86edfa91cdAndreas Huber
1827cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden    private void handleOnAllPrintJobsHandled() {
1837cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden        mHasActivePrintJobs = false;
1847cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden        if (!isBound()) {
1857cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden            // The service is dead and neither has active jobs nor discovery
1867cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden            // session, so ensure we are unbound since the service has no work.
1877cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden            if (mServiceDied && !mHasPrinterDiscoverySession) {
1887cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                ensureUnbound();
1897cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                return;
1907cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden            }
1917cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden            ensureBound();
1927cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden            mPendingCommands.add(new Runnable() {
1937cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                @Override
1947cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                public void run() {
1957cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                    handleOnAllPrintJobsHandled();
1967cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                }
1977cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden            });
1987cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden        } else {
1997cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden            if (DEBUG) {
2007cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                Slog.i(LOG_TAG, "[user: " + mUserId + "] onAllPrintJobsHandled()");
2017cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden            }
2025778822d86b0337407514b9372562b86edfa91cdAndreas Huber            // If the service has a printer discovery session
2035778822d86b0337407514b9372562b86edfa91cdAndreas Huber            // created we should not disconnect from it just yet.
2045778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (!mHasPrinterDiscoverySession) {
2055778822d86b0337407514b9372562b86edfa91cdAndreas Huber                ensureUnbound();
2065778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
2075778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
2085778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
2095778822d86b0337407514b9372562b86edfa91cdAndreas Huber
2105778822d86b0337407514b9372562b86edfa91cdAndreas Huber    public void onRequestCancelPrintJob(PrintJobInfo printJob) {
2115778822d86b0337407514b9372562b86edfa91cdAndreas Huber        Handler.getMain().sendMessage(obtainMessage(
2125778822d86b0337407514b9372562b86edfa91cdAndreas Huber                RemotePrintService::handleRequestCancelPrintJob, this, printJob));
2135778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
2145778822d86b0337407514b9372562b86edfa91cdAndreas Huber
2155778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private void handleRequestCancelPrintJob(final PrintJobInfo printJob) {
216c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber        if (!isBound()) {
217c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber            ensureBound();
218c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber            mPendingCommands.add(new Runnable() {
219c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber                @Override
220c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber                public void run() {
221c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber                    handleRequestCancelPrintJob(printJob);
222c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber                }
2235778822d86b0337407514b9372562b86edfa91cdAndreas Huber            });
2245778822d86b0337407514b9372562b86edfa91cdAndreas Huber        } else {
2255778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (DEBUG) {
2265778822d86b0337407514b9372562b86edfa91cdAndreas Huber                Slog.i(LOG_TAG, "[user: " + mUserId + "] requestCancelPrintJob()");
2275778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
2285b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber            try {
2295b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber                mPrintService.requestCancelPrintJob(printJob);
2305b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber            } catch (RemoteException re) {
2315b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber                Slog.e(LOG_TAG, "Error canceling a pring job.", re);
2325b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber            }
2335b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber        }
2345778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
2355778822d86b0337407514b9372562b86edfa91cdAndreas Huber
2365778822d86b0337407514b9372562b86edfa91cdAndreas Huber    public void onPrintJobQueued(PrintJobInfo printJob) {
2375778822d86b0337407514b9372562b86edfa91cdAndreas Huber        Handler.getMain().sendMessage(obtainMessage(
2385778822d86b0337407514b9372562b86edfa91cdAndreas Huber                RemotePrintService::handleOnPrintJobQueued, this, printJob));
2395778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
2405b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber
2415778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private void handleOnPrintJobQueued(final PrintJobInfo printJob) {
2425778822d86b0337407514b9372562b86edfa91cdAndreas Huber        mHasActivePrintJobs = true;
2435778822d86b0337407514b9372562b86edfa91cdAndreas Huber        if (!isBound()) {
2445778822d86b0337407514b9372562b86edfa91cdAndreas Huber            ensureBound();
2455778822d86b0337407514b9372562b86edfa91cdAndreas Huber            mPendingCommands.add(new Runnable() {
2464b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber                @Override
2474b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber                public void run() {
2484b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber                    handleOnPrintJobQueued(printJob);
2494b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber                }
2504b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber            });
2514b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber        } else {
2524b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber            if (DEBUG) {
2534b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber                Slog.i(LOG_TAG, "[user: " + mUserId + "] onPrintJobQueued()");
2544b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber            }
2555b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber            try {
2565b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber                mPrintService.onPrintJobQueued(printJob);
2575b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber            } catch (RemoteException re) {
2585b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber                Slog.e(LOG_TAG, "Error announcing queued pring job.", re);
2595b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber            }
2605b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber        }
2614b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber    }
2624b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber
2634b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber    public void createPrinterDiscoverySession() {
2644b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber        Handler.getMain().sendMessage(obtainMessage(
2654b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber                RemotePrintService::handleCreatePrinterDiscoverySession, this));
2664b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber    }
2674b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber
2684b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber    private void handleCreatePrinterDiscoverySession() {
2694b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber        mHasPrinterDiscoverySession = true;
2704b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber        if (!isBound()) {
2715b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber            ensureBound();
2724b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber            mPendingCommands.add(new Runnable() {
2734b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber                @Override
2745b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber                public void run() {
2755b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber                    handleCreatePrinterDiscoverySession();
2765b8987e7de9d04b09153f329c680d2316cdb44ecAndreas Huber                }
2774b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber            });
2784b75a9c8b93a90749bc5d22912ad0d96c12f4ecfAndreas Huber        } else {
2795778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (DEBUG) {
2805778822d86b0337407514b9372562b86edfa91cdAndreas Huber                Slog.i(LOG_TAG, "[user: " + mUserId + "] createPrinterDiscoverySession()");
2815778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
2825778822d86b0337407514b9372562b86edfa91cdAndreas Huber            try {
2835778822d86b0337407514b9372562b86edfa91cdAndreas Huber                mPrintService.createPrinterDiscoverySession();
2845778822d86b0337407514b9372562b86edfa91cdAndreas Huber            } catch (RemoteException re) {
2855778822d86b0337407514b9372562b86edfa91cdAndreas Huber                Slog.e(LOG_TAG, "Error creating printer discovery session.", re);
2865778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
2875778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
2885778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
2895778822d86b0337407514b9372562b86edfa91cdAndreas Huber
2905778822d86b0337407514b9372562b86edfa91cdAndreas Huber    public void destroyPrinterDiscoverySession() {
2915778822d86b0337407514b9372562b86edfa91cdAndreas Huber        Handler.getMain().sendMessage(obtainMessage(
2925778822d86b0337407514b9372562b86edfa91cdAndreas Huber                RemotePrintService::handleDestroyPrinterDiscoverySession, this));
2935778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
2945778822d86b0337407514b9372562b86edfa91cdAndreas Huber
2955778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private void handleDestroyPrinterDiscoverySession() {
2965778822d86b0337407514b9372562b86edfa91cdAndreas Huber        mHasPrinterDiscoverySession = false;
2975778822d86b0337407514b9372562b86edfa91cdAndreas Huber        if (!isBound()) {
2985778822d86b0337407514b9372562b86edfa91cdAndreas Huber            // The service is dead and neither has active jobs nor discovery
2995778822d86b0337407514b9372562b86edfa91cdAndreas Huber            // session, so ensure we are unbound since the service has no work.
3005778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (mServiceDied && !mHasActivePrintJobs) {
3015778822d86b0337407514b9372562b86edfa91cdAndreas Huber                ensureUnbound();
3025778822d86b0337407514b9372562b86edfa91cdAndreas Huber                return;
3035778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
3045778822d86b0337407514b9372562b86edfa91cdAndreas Huber            ensureBound();
3055778822d86b0337407514b9372562b86edfa91cdAndreas Huber            mPendingCommands.add(new Runnable() {
3065778822d86b0337407514b9372562b86edfa91cdAndreas Huber                @Override
3075778822d86b0337407514b9372562b86edfa91cdAndreas Huber                public void run() {
3085778822d86b0337407514b9372562b86edfa91cdAndreas Huber                    handleDestroyPrinterDiscoverySession();
3095778822d86b0337407514b9372562b86edfa91cdAndreas Huber                }
3105778822d86b0337407514b9372562b86edfa91cdAndreas Huber            });
3115778822d86b0337407514b9372562b86edfa91cdAndreas Huber        } else {
3125778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (DEBUG) {
3135778822d86b0337407514b9372562b86edfa91cdAndreas Huber                Slog.i(LOG_TAG, "[user: " + mUserId + "] destroyPrinterDiscoverySession()");
3145778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
3155778822d86b0337407514b9372562b86edfa91cdAndreas Huber            try {
3165778822d86b0337407514b9372562b86edfa91cdAndreas Huber                mPrintService.destroyPrinterDiscoverySession();
3175778822d86b0337407514b9372562b86edfa91cdAndreas Huber            } catch (RemoteException re) {
3185778822d86b0337407514b9372562b86edfa91cdAndreas Huber                Slog.e(LOG_TAG, "Error destroying printer dicovery session.", re);
3195778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
3205778822d86b0337407514b9372562b86edfa91cdAndreas Huber            // If the service has no print jobs and no active discovery
3215778822d86b0337407514b9372562b86edfa91cdAndreas Huber            // session anymore we should disconnect from it.
3225778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (!mHasActivePrintJobs) {
3235778822d86b0337407514b9372562b86edfa91cdAndreas Huber                ensureUnbound();
3245778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
3255778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
3265778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
3275778822d86b0337407514b9372562b86edfa91cdAndreas Huber
328fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar    public void startPrinterDiscovery(List<PrinterId> priorityList) {
329fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar        Handler.getMain().sendMessage(obtainMessage(
330fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar                RemotePrintService::handleStartPrinterDiscovery, this, priorityList));
331fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar    }
332fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar
333fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar    private void handleStartPrinterDiscovery(final List<PrinterId> priorityList) {
334fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar        // Take a note that we are doing discovery.
335fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar        mDiscoveryPriorityList = new ArrayList<PrinterId>();
336fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar        if (priorityList != null) {
337fc7fca77caa12993dd938d5ff43797d781291027Lajos Molnar            mDiscoveryPriorityList.addAll(priorityList);
3385778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
3395778822d86b0337407514b9372562b86edfa91cdAndreas Huber        if (!isBound()) {
3405778822d86b0337407514b9372562b86edfa91cdAndreas Huber            ensureBound();
3415778822d86b0337407514b9372562b86edfa91cdAndreas Huber            mPendingCommands.add(new Runnable() {
3425778822d86b0337407514b9372562b86edfa91cdAndreas Huber                @Override
3435778822d86b0337407514b9372562b86edfa91cdAndreas Huber                public void run() {
3445778822d86b0337407514b9372562b86edfa91cdAndreas Huber                    handleStartPrinterDiscovery(priorityList);
3455778822d86b0337407514b9372562b86edfa91cdAndreas Huber                }
3467cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden            });
3477cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden        } else {
3487cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden            if (DEBUG) {
3497cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                Slog.i(LOG_TAG, "[user: " + mUserId + "] startPrinterDiscovery()");
3507cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden            }
3517cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden            try {
3527cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                mPrintService.startPrinterDiscovery(priorityList);
3535778822d86b0337407514b9372562b86edfa91cdAndreas Huber            } catch (RemoteException re) {
3545778822d86b0337407514b9372562b86edfa91cdAndreas Huber                Slog.e(LOG_TAG, "Error starting printer dicovery.", re);
3555778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
3565778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
3575778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
3585778822d86b0337407514b9372562b86edfa91cdAndreas Huber
3595778822d86b0337407514b9372562b86edfa91cdAndreas Huber    public void stopPrinterDiscovery() {
3605778822d86b0337407514b9372562b86edfa91cdAndreas Huber        Handler.getMain().sendMessage(obtainMessage(
3615778822d86b0337407514b9372562b86edfa91cdAndreas Huber                RemotePrintService::handleStopPrinterDiscovery, this));
3625778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
3635778822d86b0337407514b9372562b86edfa91cdAndreas Huber
3645778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private void handleStopPrinterDiscovery() {
3655778822d86b0337407514b9372562b86edfa91cdAndreas Huber        // We are not doing discovery anymore.
3665778822d86b0337407514b9372562b86edfa91cdAndreas Huber        mDiscoveryPriorityList = null;
367e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar        if (!isBound()) {
368e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            ensureBound();
369e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            mPendingCommands.add(new Runnable() {
370e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar                @Override
371e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar                public void run() {
372e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar                    handleStopPrinterDiscovery();
373e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar                }
374e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            });
375e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar        } else {
376e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            if (DEBUG) {
377e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar                Slog.i(LOG_TAG, "[user: " + mUserId + "] stopPrinterDiscovery()");
378e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            }
379e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar
380e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            // Stop tracking printers.
381717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo            stopTrackingAllPrinters();
382717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo
383717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo            try {
384717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo                mPrintService.stopPrinterDiscovery();
385717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo            } catch (RemoteException re) {
386717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo                Slog.e(LOG_TAG, "Error stopping printer discovery.", re);
387717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo            }
388717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo        }
389717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo    }
390717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo
391717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo    public void validatePrinters(List<PrinterId> printerIds) {
392717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo        Handler.getMain().sendMessage(obtainMessage(
393717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo                RemotePrintService::handleValidatePrinters, this, printerIds));
394717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo    }
3955778822d86b0337407514b9372562b86edfa91cdAndreas Huber
3965778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private void handleValidatePrinters(final List<PrinterId> printerIds) {
3975778822d86b0337407514b9372562b86edfa91cdAndreas Huber        if (!isBound()) {
3985778822d86b0337407514b9372562b86edfa91cdAndreas Huber            ensureBound();
3995778822d86b0337407514b9372562b86edfa91cdAndreas Huber            mPendingCommands.add(new Runnable() {
4005778822d86b0337407514b9372562b86edfa91cdAndreas Huber                @Override
4015778822d86b0337407514b9372562b86edfa91cdAndreas Huber                public void run() {
4025778822d86b0337407514b9372562b86edfa91cdAndreas Huber                    handleValidatePrinters(printerIds);
4035778822d86b0337407514b9372562b86edfa91cdAndreas Huber                }
4045778822d86b0337407514b9372562b86edfa91cdAndreas Huber            });
4055778822d86b0337407514b9372562b86edfa91cdAndreas Huber        } else {
4065778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (DEBUG) {
4075778822d86b0337407514b9372562b86edfa91cdAndreas Huber                Slog.i(LOG_TAG, "[user: " + mUserId + "] validatePrinters()");
4085778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
4095778822d86b0337407514b9372562b86edfa91cdAndreas Huber            try {
4105778822d86b0337407514b9372562b86edfa91cdAndreas Huber                mPrintService.validatePrinters(printerIds);
4115778822d86b0337407514b9372562b86edfa91cdAndreas Huber            } catch (RemoteException re) {
4125778822d86b0337407514b9372562b86edfa91cdAndreas Huber                Slog.e(LOG_TAG, "Error requesting printers validation.", re);
4137bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar            }
4147bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar        }
4157bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar    }
4167bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar
4177bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar    public void startPrinterStateTracking(@NonNull PrinterId printerId) {
4187bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar        Handler.getMain().sendMessage(obtainMessage(
4197bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar                RemotePrintService::handleStartPrinterStateTracking, this, printerId));
4207bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar    }
4217bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar
4227bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar    /**
4237bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar     * Queue a request for a custom printer icon for a printer.
4247bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar     *
4257bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar     * @param printerId the id of the printer the icon should be loaded for
4267bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar     * @see android.print.PrinterInfo.Builder#setHasCustomPrinterIcon
4277bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar     */
4287bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar    public void requestCustomPrinterIcon(@NonNull PrinterId printerId) {
4297bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar        Handler.getMain().sendMessage(obtainMessage(
4307bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar                RemotePrintService::handleRequestCustomPrinterIcon, this, printerId));
4317bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar    }
4327bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar
4337bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar    /**
4347bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar     * Request a custom printer icon for a printer.
4357bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar     *
4367bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar     * @param printerId the id of the printer the icon should be loaded for
4377bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar     * @see android.print.PrinterInfo.Builder#setHasCustomPrinterIcon
4387bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar     */
4397bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar    private void handleRequestCustomPrinterIcon(@NonNull PrinterId printerId) {
4407bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar        if (!isBound()) {
4417bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar            ensureBound();
4427bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar            mPendingCommands.add(() -> handleRequestCustomPrinterIcon(printerId));
4437bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar        } else {
4447bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar            if (DEBUG) {
4457bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar                Slog.i(LOG_TAG, "[user: " + mUserId + "] requestCustomPrinterIcon()");
4467bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar            }
4477bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar
4487bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar            try {
4497bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar                mPrintService.requestCustomPrinterIcon(printerId);
4507bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar            } catch (RemoteException re) {
4517bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar                Slog.e(LOG_TAG, "Error requesting icon for " + printerId, re);
4527bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar            }
4535778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
4545778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
4555778822d86b0337407514b9372562b86edfa91cdAndreas Huber
4565778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private void handleStartPrinterStateTracking(final @NonNull PrinterId printerId) {
4575778822d86b0337407514b9372562b86edfa91cdAndreas Huber        synchronized (mLock) {
4585778822d86b0337407514b9372562b86edfa91cdAndreas Huber            // Take a note we are tracking the printer.
4595778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (mTrackedPrinterList == null) {
460496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber                mTrackedPrinterList = new ArrayList<PrinterId>();
461496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber            }
462496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber            mTrackedPrinterList.add(printerId);
463496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber        }
464496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber
465496238cc7551d414067dcbbb4fe3bd801f205f95Andreas Huber        if (!isBound()) {
466575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber            ensureBound();
467575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber            mPendingCommands.add(new Runnable() {
468575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber                @Override
469575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber                public void run() {
470575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber                    handleStartPrinterStateTracking(printerId);
471575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber                }
4725778822d86b0337407514b9372562b86edfa91cdAndreas Huber            });
4735778822d86b0337407514b9372562b86edfa91cdAndreas Huber        } else {
4745778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (DEBUG) {
4755778822d86b0337407514b9372562b86edfa91cdAndreas Huber                Slog.i(LOG_TAG, "[user: " + mUserId + "] startPrinterTracking()");
4765778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
4775778822d86b0337407514b9372562b86edfa91cdAndreas Huber            try {
4785778822d86b0337407514b9372562b86edfa91cdAndreas Huber                mPrintService.startPrinterStateTracking(printerId);
4795778822d86b0337407514b9372562b86edfa91cdAndreas Huber            } catch (RemoteException re) {
4805778822d86b0337407514b9372562b86edfa91cdAndreas Huber                Slog.e(LOG_TAG, "Error requesting start printer tracking.", re);
4815778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
4825778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
4835778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
4845778822d86b0337407514b9372562b86edfa91cdAndreas Huber
4855778822d86b0337407514b9372562b86edfa91cdAndreas Huber    public void stopPrinterStateTracking(PrinterId printerId) {
4865778822d86b0337407514b9372562b86edfa91cdAndreas Huber        Handler.getMain().sendMessage(obtainMessage(
4875778822d86b0337407514b9372562b86edfa91cdAndreas Huber                RemotePrintService::handleStopPrinterStateTracking, this, printerId));
4885778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
4895778822d86b0337407514b9372562b86edfa91cdAndreas Huber
4905778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private void handleStopPrinterStateTracking(final PrinterId printerId) {
4915778822d86b0337407514b9372562b86edfa91cdAndreas Huber        synchronized (mLock) {
4925778822d86b0337407514b9372562b86edfa91cdAndreas Huber            // We are no longer tracking the printer.
4935778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (mTrackedPrinterList == null || !mTrackedPrinterList.remove(printerId)) {
4945778822d86b0337407514b9372562b86edfa91cdAndreas Huber                return;
4955778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
4965778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (mTrackedPrinterList.isEmpty()) {
4975778822d86b0337407514b9372562b86edfa91cdAndreas Huber                mTrackedPrinterList = null;
4985778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
4995778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
5005778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5015778822d86b0337407514b9372562b86edfa91cdAndreas Huber        if (!isBound()) {
5025778822d86b0337407514b9372562b86edfa91cdAndreas Huber            ensureBound();
5035778822d86b0337407514b9372562b86edfa91cdAndreas Huber            mPendingCommands.add(new Runnable() {
5045778822d86b0337407514b9372562b86edfa91cdAndreas Huber                @Override
5055778822d86b0337407514b9372562b86edfa91cdAndreas Huber                public void run() {
5065778822d86b0337407514b9372562b86edfa91cdAndreas Huber                    handleStopPrinterStateTracking(printerId);
5075778822d86b0337407514b9372562b86edfa91cdAndreas Huber                }
5085778822d86b0337407514b9372562b86edfa91cdAndreas Huber            });
5095778822d86b0337407514b9372562b86edfa91cdAndreas Huber        } else {
5105778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (DEBUG) {
5115778822d86b0337407514b9372562b86edfa91cdAndreas Huber                Slog.i(LOG_TAG, "[user: " + mUserId + "] stopPrinterTracking()");
5125778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
5135778822d86b0337407514b9372562b86edfa91cdAndreas Huber            try {
5145778822d86b0337407514b9372562b86edfa91cdAndreas Huber                mPrintService.stopPrinterStateTracking(printerId);
5155778822d86b0337407514b9372562b86edfa91cdAndreas Huber            } catch (RemoteException re) {
5165778822d86b0337407514b9372562b86edfa91cdAndreas Huber                Slog.e(LOG_TAG, "Error requesting stop printer tracking.", re);
5175778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
5185778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
5195778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
5205778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5215778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private void stopTrackingAllPrinters() {
5225778822d86b0337407514b9372562b86edfa91cdAndreas Huber        synchronized (mLock) {
5235778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (mTrackedPrinterList == null) {
5245778822d86b0337407514b9372562b86edfa91cdAndreas Huber                return;
5255778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
5265778822d86b0337407514b9372562b86edfa91cdAndreas Huber            final int trackedPrinterCount = mTrackedPrinterList.size();
5275778822d86b0337407514b9372562b86edfa91cdAndreas Huber            for (int i = trackedPrinterCount - 1; i >= 0; i--) {
5285778822d86b0337407514b9372562b86edfa91cdAndreas Huber                PrinterId printerId = mTrackedPrinterList.get(i);
5295778822d86b0337407514b9372562b86edfa91cdAndreas Huber                if (printerId.getServiceName().equals(mComponentName)) {
5305778822d86b0337407514b9372562b86edfa91cdAndreas Huber                    handleStopPrinterStateTracking(printerId);
5315778822d86b0337407514b9372562b86edfa91cdAndreas Huber                }
5325778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
5335778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
5345778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
5355778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5365778822d86b0337407514b9372562b86edfa91cdAndreas Huber    public void dump(@NonNull DualDumpOutputStream proto) {
5375778822d86b0337407514b9372562b86edfa91cdAndreas Huber        writeComponentName(proto, "component_name", ActivePrintServiceProto.COMPONENT_NAME,
5385778822d86b0337407514b9372562b86edfa91cdAndreas Huber                mComponentName);
5395778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5405778822d86b0337407514b9372562b86edfa91cdAndreas Huber        proto.write("is_destroyed", ActivePrintServiceProto.IS_DESTROYED, mDestroyed);
5415778822d86b0337407514b9372562b86edfa91cdAndreas Huber        proto.write("is_bound", ActivePrintServiceProto.IS_BOUND, isBound());
5425778822d86b0337407514b9372562b86edfa91cdAndreas Huber        proto.write("has_discovery_session", ActivePrintServiceProto.HAS_DISCOVERY_SESSION,
5435778822d86b0337407514b9372562b86edfa91cdAndreas Huber                mHasPrinterDiscoverySession);
5445778822d86b0337407514b9372562b86edfa91cdAndreas Huber        proto.write("has_active_print_jobs", ActivePrintServiceProto.HAS_ACTIVE_PRINT_JOBS,
5455778822d86b0337407514b9372562b86edfa91cdAndreas Huber                mHasActivePrintJobs);
5465778822d86b0337407514b9372562b86edfa91cdAndreas Huber        proto.write("is_discovering_printers", ActivePrintServiceProto.IS_DISCOVERING_PRINTERS,
5475778822d86b0337407514b9372562b86edfa91cdAndreas Huber                mDiscoveryPriorityList != null);
5485778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5495778822d86b0337407514b9372562b86edfa91cdAndreas Huber        synchronized (mLock) {
5505778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (mTrackedPrinterList != null) {
5515778822d86b0337407514b9372562b86edfa91cdAndreas Huber                int numTrackedPrinters = mTrackedPrinterList.size();
5525778822d86b0337407514b9372562b86edfa91cdAndreas Huber                for (int i = 0; i < numTrackedPrinters; i++) {
5535778822d86b0337407514b9372562b86edfa91cdAndreas Huber                    writePrinterId(proto, "tracked_printers",
5545778822d86b0337407514b9372562b86edfa91cdAndreas Huber                            ActivePrintServiceProto.TRACKED_PRINTERS, mTrackedPrinterList.get(i));
5555778822d86b0337407514b9372562b86edfa91cdAndreas Huber                }
5565778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
5575778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
5585778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
5595778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5605778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private boolean isBound() {
5615778822d86b0337407514b9372562b86edfa91cdAndreas Huber        return mPrintService != null;
5625778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
5635778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5645778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private void ensureBound() {
5655778822d86b0337407514b9372562b86edfa91cdAndreas Huber        if (isBound() || mBinding) {
5665778822d86b0337407514b9372562b86edfa91cdAndreas Huber            return;
5675778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
5685778822d86b0337407514b9372562b86edfa91cdAndreas Huber        if (DEBUG) {
5695778822d86b0337407514b9372562b86edfa91cdAndreas Huber            Slog.i(LOG_TAG, "[user: " + mUserId + "] ensureBound()");
5705778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
5715778822d86b0337407514b9372562b86edfa91cdAndreas Huber        mBinding = true;
5725778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5735778822d86b0337407514b9372562b86edfa91cdAndreas Huber        boolean wasBound = mContext.bindServiceAsUser(mIntent, mServiceConnection,
5745778822d86b0337407514b9372562b86edfa91cdAndreas Huber                Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
5755778822d86b0337407514b9372562b86edfa91cdAndreas Huber                        | Context.BIND_ALLOW_INSTANT, new UserHandle(mUserId));
5765778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5775778822d86b0337407514b9372562b86edfa91cdAndreas Huber        if (!wasBound) {
5785778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (DEBUG) {
5795778822d86b0337407514b9372562b86edfa91cdAndreas Huber                Slog.i(LOG_TAG, "[user: " + mUserId + "] could not bind to " + mIntent);
5805778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
5815778822d86b0337407514b9372562b86edfa91cdAndreas Huber            mBinding = false;
5825778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5835778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (!mServiceDied) {
5845778822d86b0337407514b9372562b86edfa91cdAndreas Huber                handleBinderDied();
58592cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar            }
5865778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
5875778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
5885778822d86b0337407514b9372562b86edfa91cdAndreas Huber
5895778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private void ensureUnbound() {
5905778822d86b0337407514b9372562b86edfa91cdAndreas Huber        if (!isBound() && !mBinding) {
5915778822d86b0337407514b9372562b86edfa91cdAndreas Huber            return;
5925778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
5935778822d86b0337407514b9372562b86edfa91cdAndreas Huber        if (DEBUG) {
5945778822d86b0337407514b9372562b86edfa91cdAndreas Huber            Slog.i(LOG_TAG, "[user: " + mUserId + "] ensureUnbound()");
595aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber        }
596aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber        mBinding = false;
597aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber        mPendingCommands.clear();
598aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber        mHasActivePrintJobs = false;
599aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber        mHasPrinterDiscoverySession = false;
6005778822d86b0337407514b9372562b86edfa91cdAndreas Huber        mDiscoveryPriorityList = null;
6015778822d86b0337407514b9372562b86edfa91cdAndreas Huber
6025778822d86b0337407514b9372562b86edfa91cdAndreas Huber        synchronized (mLock) {
6035778822d86b0337407514b9372562b86edfa91cdAndreas Huber            mTrackedPrinterList = null;
6045778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
6055778822d86b0337407514b9372562b86edfa91cdAndreas Huber
6065778822d86b0337407514b9372562b86edfa91cdAndreas Huber        if (isBound()) {
6075778822d86b0337407514b9372562b86edfa91cdAndreas Huber            try {
6085778822d86b0337407514b9372562b86edfa91cdAndreas Huber                mPrintService.setClient(null);
6095778822d86b0337407514b9372562b86edfa91cdAndreas Huber            } catch (RemoteException re) {
6105778822d86b0337407514b9372562b86edfa91cdAndreas Huber                /* ignore */
6115778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
6125778822d86b0337407514b9372562b86edfa91cdAndreas Huber            mPrintService.asBinder().unlinkToDeath(this, 0);
6135778822d86b0337407514b9372562b86edfa91cdAndreas Huber            mPrintService = null;
6145778822d86b0337407514b9372562b86edfa91cdAndreas Huber            mContext.unbindService(mServiceConnection);
6155778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
6165778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
6175778822d86b0337407514b9372562b86edfa91cdAndreas Huber
6185778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private class RemoteServiceConneciton implements ServiceConnection {
6195778822d86b0337407514b9372562b86edfa91cdAndreas Huber        @Override
6205778822d86b0337407514b9372562b86edfa91cdAndreas Huber        public void onServiceConnected(ComponentName name, IBinder service) {
6215778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (mDestroyed || !mBinding) {
622c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber                mContext.unbindService(mServiceConnection);
6235778822d86b0337407514b9372562b86edfa91cdAndreas Huber                return;
6245778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
6255778822d86b0337407514b9372562b86edfa91cdAndreas Huber            mBinding = false;
6265778822d86b0337407514b9372562b86edfa91cdAndreas Huber            mPrintService = IPrintService.Stub.asInterface(service);
6275778822d86b0337407514b9372562b86edfa91cdAndreas Huber            try {
62803ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber                service.linkToDeath(RemotePrintService.this, 0);
629aa7f97bb9c70176245ffb7ed0ce52bee6c1a57d7Andreas Huber            } catch (RemoteException re) {
63003ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber                handleBinderDied();
63103ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber                return;
63203ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber            }
63303ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber            try {
63403ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber                mPrintService.setClient(mPrintServiceClient);
63503ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber            } catch (RemoteException re) {
63603ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber                Slog.e(LOG_TAG, "Error setting client for: " + service, re);
63703ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber                handleBinderDied();
63803ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber                return;
63903ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber            }
64003ddaec84b65157af1dbf022a72de778dc59a63eAndreas Huber            // If the service died and there is a discovery session, recreate it.
6415778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (mServiceDied && mHasPrinterDiscoverySession) {
6425778822d86b0337407514b9372562b86edfa91cdAndreas Huber                handleCreatePrinterDiscoverySession();
6435778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
6445778822d86b0337407514b9372562b86edfa91cdAndreas Huber            // If the service died and there is discovery started, restart it.
6455778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (mServiceDied && mDiscoveryPriorityList != null) {
6465778822d86b0337407514b9372562b86edfa91cdAndreas Huber                handleStartPrinterDiscovery(mDiscoveryPriorityList);
6475778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
6485778822d86b0337407514b9372562b86edfa91cdAndreas Huber            synchronized (mLock) {
6495778822d86b0337407514b9372562b86edfa91cdAndreas Huber                // If the service died and printers were tracked, start tracking.
6505778822d86b0337407514b9372562b86edfa91cdAndreas Huber                if (mServiceDied && mTrackedPrinterList != null) {
6515778822d86b0337407514b9372562b86edfa91cdAndreas Huber                    final int trackedPrinterCount = mTrackedPrinterList.size();
6525778822d86b0337407514b9372562b86edfa91cdAndreas Huber                    for (int i = 0; i < trackedPrinterCount; i++) {
6535778822d86b0337407514b9372562b86edfa91cdAndreas Huber                        handleStartPrinterStateTracking(mTrackedPrinterList.get(i));
6545778822d86b0337407514b9372562b86edfa91cdAndreas Huber                    }
655575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber                }
6565778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
6575778822d86b0337407514b9372562b86edfa91cdAndreas Huber            // Finally, do all the pending work.
658ec5f7cc4756d389505e761b9d803a1a3a46b64d7Lajos Molnar            while (!mPendingCommands.isEmpty()) {
6595778822d86b0337407514b9372562b86edfa91cdAndreas Huber                Runnable pendingCommand = mPendingCommands.remove(0);
6605778822d86b0337407514b9372562b86edfa91cdAndreas Huber                pendingCommand.run();
6615778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
6625778822d86b0337407514b9372562b86edfa91cdAndreas Huber            // We did a best effort to get to the last state if we crashed.
6635778822d86b0337407514b9372562b86edfa91cdAndreas Huber            // If we do not have print jobs and no discovery is in progress,
6645778822d86b0337407514b9372562b86edfa91cdAndreas Huber            // then no need to be bound.
6655778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (!mHasPrinterDiscoverySession && !mHasActivePrintJobs) {
6665778822d86b0337407514b9372562b86edfa91cdAndreas Huber                ensureUnbound();
667575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber            }
668ec5f7cc4756d389505e761b9d803a1a3a46b64d7Lajos Molnar            mServiceDied = false;
6695778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
6705778822d86b0337407514b9372562b86edfa91cdAndreas Huber
6715778822d86b0337407514b9372562b86edfa91cdAndreas Huber        @Override
6725778822d86b0337407514b9372562b86edfa91cdAndreas Huber        public void onServiceDisconnected(ComponentName name) {
6735778822d86b0337407514b9372562b86edfa91cdAndreas Huber            mBinding = true;
6745778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
6755778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
6765778822d86b0337407514b9372562b86edfa91cdAndreas Huber
6775778822d86b0337407514b9372562b86edfa91cdAndreas Huber    private static final class RemotePrintServiceClient extends IPrintServiceClient.Stub {
6785778822d86b0337407514b9372562b86edfa91cdAndreas Huber        private final WeakReference<RemotePrintService> mWeakService;
6795778822d86b0337407514b9372562b86edfa91cdAndreas Huber
6805778822d86b0337407514b9372562b86edfa91cdAndreas Huber        public RemotePrintServiceClient(RemotePrintService service) {
6815778822d86b0337407514b9372562b86edfa91cdAndreas Huber            mWeakService = new WeakReference<RemotePrintService>(service);
68292cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar        }
6835778822d86b0337407514b9372562b86edfa91cdAndreas Huber
6845778822d86b0337407514b9372562b86edfa91cdAndreas Huber        @Override
6855778822d86b0337407514b9372562b86edfa91cdAndreas Huber        public List<PrintJobInfo> getPrintJobInfos() {
6865778822d86b0337407514b9372562b86edfa91cdAndreas Huber            RemotePrintService service = mWeakService.get();
687717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo            if (service != null) {
6885778822d86b0337407514b9372562b86edfa91cdAndreas Huber                final long identity = Binder.clearCallingIdentity();
689717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo                try {
6905778822d86b0337407514b9372562b86edfa91cdAndreas Huber                    return service.mSpooler.getPrintJobInfos(service.mComponentName,
6915778822d86b0337407514b9372562b86edfa91cdAndreas Huber                            PrintJobInfo.STATE_ANY_SCHEDULED, PrintManager.APP_ID_ANY);
6925778822d86b0337407514b9372562b86edfa91cdAndreas Huber                } finally {
6935778822d86b0337407514b9372562b86edfa91cdAndreas Huber                    Binder.restoreCallingIdentity(identity);
6945778822d86b0337407514b9372562b86edfa91cdAndreas Huber                }
695717fd3d4328abf524978ce9c125ab8ae8d6bffadMartin Storsjo            }
6961bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber            return null;
6971bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        }
6981bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
6991bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        @Override
7001bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber        public PrintJobInfo getPrintJobInfo(PrintJobId printJobId) {
7015778822d86b0337407514b9372562b86edfa91cdAndreas Huber            RemotePrintService service = mWeakService.get();
7025778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (service != null) {
7035778822d86b0337407514b9372562b86edfa91cdAndreas Huber                final long identity = Binder.clearCallingIdentity();
7045778822d86b0337407514b9372562b86edfa91cdAndreas Huber                try {
70592cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar                    return service.mSpooler.getPrintJobInfo(printJobId,
7065778822d86b0337407514b9372562b86edfa91cdAndreas Huber                            PrintManager.APP_ID_ANY);
7075778822d86b0337407514b9372562b86edfa91cdAndreas Huber                } finally {
7085778822d86b0337407514b9372562b86edfa91cdAndreas Huber                    Binder.restoreCallingIdentity(identity);
7095778822d86b0337407514b9372562b86edfa91cdAndreas Huber                }
7106507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden            }
7116507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden            return null;
7126507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden        }
713e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar
714e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar        @Override
715e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar        public boolean setPrintJobState(PrintJobId printJobId, int state, String error) {
7165778822d86b0337407514b9372562b86edfa91cdAndreas Huber            RemotePrintService service = mWeakService.get();
7175778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (service != null) {
7185778822d86b0337407514b9372562b86edfa91cdAndreas Huber                final long identity = Binder.clearCallingIdentity();
7195778822d86b0337407514b9372562b86edfa91cdAndreas Huber                try {
72092cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar                    return service.mSpooler.setPrintJobState(printJobId, state, error);
7217cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                } finally {
72292cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar                    Binder.restoreCallingIdentity(identity);
7237cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                }
7247cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden            }
7257cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden            return false;
7267cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden        }
7277cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden
7287cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden        @Override
7297cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden        public boolean setPrintJobTag(PrintJobId printJobId, String tag) {
7306507d14c6d10f93d390de62b9eed267f9b544985Andy McFadden            RemotePrintService service = mWeakService.get();
7317cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden            if (service != null) {
7327cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                final long identity = Binder.clearCallingIdentity();
7337cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                try {
7347cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                    return service.mSpooler.setPrintJobTag(printJobId, tag);
7357cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                } finally {
7367cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                    Binder.restoreCallingIdentity(identity);
7377cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                }
73892cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar            }
7397cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden            return false;
74092cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar        }
7417cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden
7427cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden        @Override
7437cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden        public void writePrintJobData(ParcelFileDescriptor fd, PrintJobId printJobId) {
7447cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden            RemotePrintService service = mWeakService.get();
7457cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden            if (service != null) {
7467cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                final long identity = Binder.clearCallingIdentity();
7477cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                try {
7487cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                    service.mSpooler.writePrintJobData(fd, printJobId);
7497cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                } finally {
7507cd58537932ef6f481f68be0b9c597a89cebdfecAndy McFadden                    Binder.restoreCallingIdentity(identity);
75192cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar                }
7525778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
7537bad72237b49ac47e77ffe2a89fd26f3d171324cLajos Molnar        }
7545778822d86b0337407514b9372562b86edfa91cdAndreas Huber
7555778822d86b0337407514b9372562b86edfa91cdAndreas Huber        @Override
7565778822d86b0337407514b9372562b86edfa91cdAndreas Huber        public void setProgress(@NonNull PrintJobId printJobId,
7575778822d86b0337407514b9372562b86edfa91cdAndreas Huber                @FloatRange(from=0.0, to=1.0) float progress) {
7585778822d86b0337407514b9372562b86edfa91cdAndreas Huber            RemotePrintService service = mWeakService.get();
7595778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (service != null) {
7605778822d86b0337407514b9372562b86edfa91cdAndreas Huber                final long identity = Binder.clearCallingIdentity();
7615778822d86b0337407514b9372562b86edfa91cdAndreas Huber                try {
7625778822d86b0337407514b9372562b86edfa91cdAndreas Huber                    service.mSpooler.setProgress(printJobId, progress);
7635778822d86b0337407514b9372562b86edfa91cdAndreas Huber                } finally {
7645778822d86b0337407514b9372562b86edfa91cdAndreas Huber                    Binder.restoreCallingIdentity(identity);
7655778822d86b0337407514b9372562b86edfa91cdAndreas Huber                }
7665778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
767eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber        }
768eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber
769eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber        @Override
77092cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar        public void setStatus(@NonNull PrintJobId printJobId, @Nullable CharSequence status) {
77192cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar            RemotePrintService service = mWeakService.get();
7725778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (service != null) {
773eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber                final long identity = Binder.clearCallingIdentity();
7745778822d86b0337407514b9372562b86edfa91cdAndreas Huber                try {
775eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber                    service.mSpooler.setStatus(printJobId, status);
7765778822d86b0337407514b9372562b86edfa91cdAndreas Huber                } finally {
777eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber                    Binder.restoreCallingIdentity(identity);
7785778822d86b0337407514b9372562b86edfa91cdAndreas Huber                }
779eb61431af13741aa8b7e57a39f69bba5a6c190dcAndreas Huber            }
7805778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
7811bd139a2a68690e80398b70b27ca59550fea0e65Andreas Huber
782ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        @Override
783ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber        public void setStatusRes(@NonNull PrintJobId printJobId, @StringRes int status,
784ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber                @NonNull CharSequence appPackageName) {
785ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6Andreas Huber            RemotePrintService service = mWeakService.get();
7865778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (service != null) {
7875778822d86b0337407514b9372562b86edfa91cdAndreas Huber                final long identity = Binder.clearCallingIdentity();
7885778822d86b0337407514b9372562b86edfa91cdAndreas Huber                try {
7895778822d86b0337407514b9372562b86edfa91cdAndreas Huber                    service.mSpooler.setStatus(printJobId, status, appPackageName);
7905778822d86b0337407514b9372562b86edfa91cdAndreas Huber                } finally {
7915778822d86b0337407514b9372562b86edfa91cdAndreas Huber                    Binder.restoreCallingIdentity(identity);
7925778822d86b0337407514b9372562b86edfa91cdAndreas Huber                }
7935778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
7945778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
7955778822d86b0337407514b9372562b86edfa91cdAndreas Huber
7965778822d86b0337407514b9372562b86edfa91cdAndreas Huber        @Override
7975778822d86b0337407514b9372562b86edfa91cdAndreas Huber        @SuppressWarnings({"rawtypes", "unchecked"})
798575a5361fc970476cd7979638ee3ac00cc6e5024Andreas Huber        public void onPrintersAdded(ParceledListSlice printers) {
7995778822d86b0337407514b9372562b86edfa91cdAndreas Huber            RemotePrintService service = mWeakService.get();
8005778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (service != null) {
8015778822d86b0337407514b9372562b86edfa91cdAndreas Huber                List<PrinterInfo> addedPrinters = (List<PrinterInfo>) printers.getList();
8025778822d86b0337407514b9372562b86edfa91cdAndreas Huber                throwIfPrinterIdsForPrinterInfoTampered(service.mComponentName, addedPrinters);
8035778822d86b0337407514b9372562b86edfa91cdAndreas Huber                final long identity = Binder.clearCallingIdentity();
80492cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar                try {
8055778822d86b0337407514b9372562b86edfa91cdAndreas Huber                    service.mCallbacks.onPrintersAdded(addedPrinters);
8065778822d86b0337407514b9372562b86edfa91cdAndreas Huber                } finally {
8075778822d86b0337407514b9372562b86edfa91cdAndreas Huber                    Binder.restoreCallingIdentity(identity);
8085778822d86b0337407514b9372562b86edfa91cdAndreas Huber                }
8095778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
8105778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
8115778822d86b0337407514b9372562b86edfa91cdAndreas Huber
8125778822d86b0337407514b9372562b86edfa91cdAndreas Huber        @Override
8135778822d86b0337407514b9372562b86edfa91cdAndreas Huber        @SuppressWarnings({"rawtypes", "unchecked"})
8145778822d86b0337407514b9372562b86edfa91cdAndreas Huber        public void onPrintersRemoved(ParceledListSlice printerIds) {
8155778822d86b0337407514b9372562b86edfa91cdAndreas Huber            RemotePrintService service = mWeakService.get();
8165778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (service != null) {
8175778822d86b0337407514b9372562b86edfa91cdAndreas Huber                List<PrinterId> removedPrinterIds = (List<PrinterId>) printerIds.getList();
8185778822d86b0337407514b9372562b86edfa91cdAndreas Huber                throwIfPrinterIdsTampered(service.mComponentName, removedPrinterIds);
8195778822d86b0337407514b9372562b86edfa91cdAndreas Huber                final long identity = Binder.clearCallingIdentity();
8205778822d86b0337407514b9372562b86edfa91cdAndreas Huber                try {
8216539f82d55d4457bc84ed23d57967346022c56dcMartin Storsjo                    service.mCallbacks.onPrintersRemoved(removedPrinterIds);
8226539f82d55d4457bc84ed23d57967346022c56dcMartin Storsjo                } finally {
8236539f82d55d4457bc84ed23d57967346022c56dcMartin Storsjo                    Binder.restoreCallingIdentity(identity);
8246539f82d55d4457bc84ed23d57967346022c56dcMartin Storsjo                }
8255778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
8265778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
8275778822d86b0337407514b9372562b86edfa91cdAndreas Huber
8285778822d86b0337407514b9372562b86edfa91cdAndreas Huber        private void throwIfPrinterIdsForPrinterInfoTampered(ComponentName serviceName,
8295778822d86b0337407514b9372562b86edfa91cdAndreas Huber                List<PrinterInfo> printerInfos) {
8305778822d86b0337407514b9372562b86edfa91cdAndreas Huber            final int printerInfoCount = printerInfos.size();
8315778822d86b0337407514b9372562b86edfa91cdAndreas Huber            for (int i = 0; i < printerInfoCount; i++) {
8326539f82d55d4457bc84ed23d57967346022c56dcMartin Storsjo                PrinterId printerId = printerInfos.get(i).getId();
8336539f82d55d4457bc84ed23d57967346022c56dcMartin Storsjo                throwIfPrinterIdTampered(serviceName, printerId);
8345778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
8355778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
8365778822d86b0337407514b9372562b86edfa91cdAndreas Huber
8375778822d86b0337407514b9372562b86edfa91cdAndreas Huber        private void throwIfPrinterIdsTampered(ComponentName serviceName,
8385778822d86b0337407514b9372562b86edfa91cdAndreas Huber                List<PrinterId> printerIds) {
8395778822d86b0337407514b9372562b86edfa91cdAndreas Huber            final int printerIdCount = printerIds.size();
8405778822d86b0337407514b9372562b86edfa91cdAndreas Huber            for (int i = 0; i < printerIdCount; i++) {
8415778822d86b0337407514b9372562b86edfa91cdAndreas Huber                PrinterId printerId = printerIds.get(i);
842e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber                throwIfPrinterIdTampered(serviceName, printerId);
843e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber            }
844e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber        }
845e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber
846e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber        private void throwIfPrinterIdTampered(ComponentName serviceName, PrinterId printerId) {
847e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber            if (printerId == null || !printerId.getServiceName().equals(serviceName)) {
848e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber                throw new IllegalArgumentException("Invalid printer id: " + printerId);
849e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber            }
850e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber        }
851e96ee699aca0f711d41e6c0833e5de2341c4a36dAndreas Huber
8525778822d86b0337407514b9372562b86edfa91cdAndreas Huber        @Override
8535778822d86b0337407514b9372562b86edfa91cdAndreas Huber        public void onCustomPrinterIconLoaded(PrinterId printerId, Icon icon)
8545778822d86b0337407514b9372562b86edfa91cdAndreas Huber                throws RemoteException {
85592cd05b8f2e994aabcdda5d7454c96a707dc9579Lajos Molnar            RemotePrintService service = mWeakService.get();
8565778822d86b0337407514b9372562b86edfa91cdAndreas Huber            if (service != null) {
8575778822d86b0337407514b9372562b86edfa91cdAndreas Huber                final long identity = Binder.clearCallingIdentity();
8585778822d86b0337407514b9372562b86edfa91cdAndreas Huber                try {
859c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber                    service.mCallbacks.onCustomPrinterIconLoaded(printerId, icon);
860c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber                } finally {
861c95c2ddcdfc974f42408a377fbe2de51b94a8c94Andreas Huber                    Binder.restoreCallingIdentity(identity);
8625778822d86b0337407514b9372562b86edfa91cdAndreas Huber                }
8635778822d86b0337407514b9372562b86edfa91cdAndreas Huber            }
8645778822d86b0337407514b9372562b86edfa91cdAndreas Huber        }
8655778822d86b0337407514b9372562b86edfa91cdAndreas Huber    }
8668ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber}
8678ee516a515c70a492c395b67ce12e19e7d159804Andreas Huber