1a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov/*
2a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * Copyright (C) 2013 The Android Open Source Project
3a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov *
4a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * Licensed under the Apache License, Version 2.0 (the "License");
5a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * you may not use this file except in compliance with the License.
6a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * You may obtain a copy of the License at
7a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov *
8a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov *      http://www.apache.org/licenses/LICENSE-2.0
9a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov *
10a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * Unless required by applicable law or agreed to in writing, software
11a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * distributed under the License is distributed on an "AS IS" BASIS,
12a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * See the License for the specific language governing permissions and
14a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * limitations under the License.
15a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov */
16a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
17a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovpackage com.android.server.print;
18a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
19b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmannimport android.annotation.FloatRange;
20b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmannimport android.annotation.NonNull;
21b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmannimport android.annotation.Nullable;
22d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmannimport android.annotation.StringRes;
23a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.content.ComponentName;
24a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.content.Context;
25a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.content.Intent;
26a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.content.ServiceConnection;
27bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmannimport android.graphics.drawable.Icon;
28a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.os.Binder;
29f983d084e7b8a6de722d9cede1c0cf73831c8e92Svet Ganovimport android.os.Build;
30a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.os.IBinder;
31a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.os.ParcelFileDescriptor;
32a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.os.RemoteException;
33a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.os.SystemClock;
34a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.os.UserHandle;
35a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.IPrintSpooler;
36a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.IPrintSpoolerCallbacks;
37a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.IPrintSpoolerClient;
382fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslavimport android.print.PrintJobId;
39a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.PrintJobInfo;
4066c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmannimport android.print.PrintManager;
41bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmannimport android.print.PrinterId;
428141bdfa56f13c3946bed12ba7801e492ec25c11Philip P. Moltmannimport android.printservice.PrintService;
43a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.util.Slog;
44a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.util.TimedRemoteCaller;
45a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
468141bdfa56f13c3946bed12ba7801e492ec25c11Philip P. Moltmannimport libcore.io.IoUtils;
478141bdfa56f13c3946bed12ba7801e492ec25c11Philip P. Moltmann
48b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganovimport java.io.FileDescriptor;
49b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganovimport java.io.PrintWriter;
50a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport java.lang.ref.WeakReference;
51a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport java.util.List;
52a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport java.util.concurrent.TimeoutException;
53a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
54a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov/**
55a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * This represents the remote print spooler as a local object to the
56a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * PrintManagerService. It is responsible to connecting to the remote
57a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * spooler if needed, to make the timed remote calls, to handle
58a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * remote exceptions, and to bind/unbind to the remote instance as
59a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * needed.
601d6e7cc536cb7f49b318f630ad8f2eb348786716Philip P. Moltmann *
611d6e7cc536cb7f49b318f630ad8f2eb348786716Philip P. Moltmann * The calls might be blocking and need the main thread of to be unblocked to finish. Hence do not
621d6e7cc536cb7f49b318f630ad8f2eb348786716Philip P. Moltmann * call this while holding any monitors that might need to be acquired the main thread.
63a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov */
64a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovfinal class RemotePrintSpooler {
65a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
66a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private static final String LOG_TAG = "RemotePrintSpooler";
67a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
68c6066799ad130140159230d14451b429eb828755Svetoslav    private static final boolean DEBUG = false;
69a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
70f983d084e7b8a6de722d9cede1c0cf73831c8e92Svet Ganov    private static final long BIND_SPOOLER_SERVICE_TIMEOUT =
71f983d084e7b8a6de722d9cede1c0cf73831c8e92Svet Ganov            ("eng".equals(Build.TYPE)) ? 120000 : 10000;
72a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
73a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final Object mLock = new Object();
74a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
75a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final GetPrintJobInfosCaller mGetPrintJobInfosCaller = new GetPrintJobInfosCaller();
76a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
77a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final GetPrintJobInfoCaller mGetPrintJobInfoCaller = new GetPrintJobInfoCaller();
78a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
79a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final SetPrintJobStateCaller mSetPrintJobStatusCaller = new SetPrintJobStateCaller();
80a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
81a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final SetPrintJobTagCaller mSetPrintJobTagCaller = new SetPrintJobTagCaller();
82a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
83bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    private final OnCustomPrinterIconLoadedCaller mCustomPrinterIconLoadedCaller =
84bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            new OnCustomPrinterIconLoadedCaller();
85bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
86bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    private final ClearCustomPrinterIconCacheCaller mClearCustomPrinterIconCache =
87bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            new ClearCustomPrinterIconCacheCaller();
88bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
89bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    private final GetCustomPrinterIconCaller mGetCustomPrinterIconCaller =
90bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            new GetCustomPrinterIconCaller();
91bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
92a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final ServiceConnection mServiceConnection = new MyServiceConnection();
93a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
94a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final Context mContext;
95a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
96a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final UserHandle mUserHandle;
97a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
98a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final PrintSpoolerClient mClient;
99a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
100a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final Intent mIntent;
101a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
102a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final PrintSpoolerCallbacks mCallbacks;
103a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
104e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann    private boolean mIsLowPriority;
105e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann
106a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private IPrintSpooler mRemoteInstance;
107a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
108a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private boolean mDestroyed;
109a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
11085b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov    private boolean mCanUnbind;
11185b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov
112a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    public static interface PrintSpoolerCallbacks {
113a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onPrintJobQueued(PrintJobInfo printJob);
114a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onAllPrintJobsForServiceHandled(ComponentName printService);
115dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov        public void onPrintJobStateChanged(PrintJobInfo printJob);
116a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
117a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
118e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann    public RemotePrintSpooler(Context context, int userId, boolean lowPriority,
119a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            PrintSpoolerCallbacks callbacks) {
120a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        mContext = context;
121a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        mUserHandle = new UserHandle(userId);
122a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        mCallbacks = callbacks;
123e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann        mIsLowPriority = lowPriority;
124a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        mClient = new PrintSpoolerClient(this);
125a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        mIntent = new Intent();
12666c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann        mIntent.setComponent(new ComponentName(PrintManager.PRINT_SPOOLER_PACKAGE_NAME,
12766c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann                PrintManager.PRINT_SPOOLER_PACKAGE_NAME + ".model.PrintSpoolerService"));
128a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
129a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
130e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann    public void increasePriority() {
131e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann        if (mIsLowPriority) {
132e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann            mIsLowPriority = false;
133e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann
134e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann            synchronized (mLock) {
135e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                throwIfDestroyedLocked();
136e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann
137e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                while (!mCanUnbind) {
138e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                    try {
139e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                        mLock.wait();
140e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                    } catch (InterruptedException e) {
141e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                        Slog.e(LOG_TAG, "Interrupted while waiting for operation to complete");
142e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                    }
143e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                }
144e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann
145e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                if (DEBUG) {
146e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                    Slog.i(LOG_TAG, "Unbinding as previous binding was low priority");
147e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                }
148e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann
149e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                unbindLocked();
150e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann            }
151e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann        }
152e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann    }
153e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann
154a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    public final List<PrintJobInfo> getPrintJobInfos(ComponentName componentName, int state,
155a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            int appId) {
156a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        throwIfCalledOnMainThread();
157a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        synchronized (mLock) {
158a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            throwIfDestroyedLocked();
15985b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            mCanUnbind = false;
160a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
161a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        try {
162a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            return mGetPrintJobInfosCaller.getPrintJobInfos(getRemoteInstanceLazy(),
163a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    componentName, state, appId);
164a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        } catch (RemoteException re) {
165a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            Slog.e(LOG_TAG, "Error getting print jobs.", re);
166a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        } catch (TimeoutException te) {
167a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            Slog.e(LOG_TAG, "Error getting print jobs.", te);
16885b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov        } finally {
169835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            if (DEBUG) {
170835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] getPrintJobInfos()");
171835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            }
17285b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            synchronized (mLock) {
17385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mCanUnbind = true;
17485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mLock.notifyAll();
17585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            }
176a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
177a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        return null;
178a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
179a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
1807bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav    public final void createPrintJob(PrintJobInfo printJob) {
181a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        throwIfCalledOnMainThread();
182a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        synchronized (mLock) {
183a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            throwIfDestroyedLocked();
18485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            mCanUnbind = false;
185a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
186a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        try {
1877bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            getRemoteInstanceLazy().createPrintJob(printJob);
188a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        } catch (RemoteException re) {
189a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            Slog.e(LOG_TAG, "Error creating print job.", re);
190a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        } catch (TimeoutException te) {
191a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            Slog.e(LOG_TAG, "Error creating print job.", te);
19285b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov        } finally {
193835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            if (DEBUG) {
194835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] createPrintJob()");
195835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            }
19685b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            synchronized (mLock) {
19785b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mCanUnbind = true;
19885b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mLock.notifyAll();
19985b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            }
200a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
201a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
202a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
2032fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    public final void writePrintJobData(ParcelFileDescriptor fd, PrintJobId printJobId) {
204a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        throwIfCalledOnMainThread();
205a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        synchronized (mLock) {
206a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            throwIfDestroyedLocked();
20785b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            mCanUnbind = false;
208a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
209a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        try {
210a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            getRemoteInstanceLazy().writePrintJobData(fd, printJobId);
211a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        } catch (RemoteException re) {
212a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            Slog.e(LOG_TAG, "Error writing print job data.", re);
213a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        } catch (TimeoutException te) {
214a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            Slog.e(LOG_TAG, "Error writing print job data.", te);
215a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        } finally {
216835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            if (DEBUG) {
217835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] writePrintJobData()");
218835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            }
219a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            // We passed the file descriptor across and now the other
220a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            // side is responsible to close it, so close the local copy.
221a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            IoUtils.closeQuietly(fd);
22285b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            synchronized (mLock) {
22385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mCanUnbind = true;
22485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mLock.notifyAll();
22585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            }
226a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
227a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
228a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
2292fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    public final PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId) {
230a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        throwIfCalledOnMainThread();
231a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        synchronized (mLock) {
232a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            throwIfDestroyedLocked();
23385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            mCanUnbind = false;
234a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
235a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        try {
236a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            return mGetPrintJobInfoCaller.getPrintJobInfo(getRemoteInstanceLazy(),
237a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    printJobId, appId);
238a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        } catch (RemoteException re) {
239a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            Slog.e(LOG_TAG, "Error getting print job info.", re);
240a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        } catch (TimeoutException te) {
241a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            Slog.e(LOG_TAG, "Error getting print job info.", te);
24285b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov        } finally {
243835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            if (DEBUG) {
244835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] getPrintJobInfo()");
245835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            }
24685b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            synchronized (mLock) {
24785b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mCanUnbind = true;
24885b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mLock.notifyAll();
24985b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            }
250a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
251a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        return null;
252a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
253a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
2542fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    public final boolean setPrintJobState(PrintJobId printJobId, int state, String error) {
255a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        throwIfCalledOnMainThread();
256a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        synchronized (mLock) {
257a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            throwIfDestroyedLocked();
25885b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            mCanUnbind = false;
259a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
260a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        try {
261a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            return mSetPrintJobStatusCaller.setPrintJobState(getRemoteInstanceLazy(),
2628c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov                    printJobId, state, error);
263a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        } catch (RemoteException re) {
264a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            Slog.e(LOG_TAG, "Error setting print job state.", re);
265a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        } catch (TimeoutException te) {
266a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            Slog.e(LOG_TAG, "Error setting print job state.", te);
26785b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov        } finally {
268835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            if (DEBUG) {
269835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setPrintJobState()");
270835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            }
27185b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            synchronized (mLock) {
27285b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mCanUnbind = true;
27385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mLock.notifyAll();
27485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            }
275a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
276a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        return false;
277a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
278a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
279b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann    /**
280b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann     * Set progress of a print job.
281b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann     *
282b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann     * @param printJobId The print job to update
283b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann     * @param progress The new progress
284b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann     */
285b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann    public final void setProgress(@NonNull PrintJobId printJobId,
286b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            @FloatRange(from=0.0, to=1.0) float progress) {
287b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        throwIfCalledOnMainThread();
288b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        synchronized (mLock) {
289b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            throwIfDestroyedLocked();
290b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            mCanUnbind = false;
291b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        }
292b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        try {
293b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            getRemoteInstanceLazy().setProgress(printJobId, progress);
294b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        } catch (RemoteException|TimeoutException re) {
295b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            Slog.e(LOG_TAG, "Error setting progress.", re);
296b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        } finally {
297b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            if (DEBUG) {
298b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setProgress()");
299b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            }
300b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            synchronized (mLock) {
301b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann                mCanUnbind = true;
302b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann                mLock.notifyAll();
303b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            }
304b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        }
305b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann    }
306b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann
307b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann    /**
308b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann     * Set status of a print job.
309b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann     *
310b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann     * @param printJobId The print job to update
311b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann     * @param status The new status
312b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann     */
313b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann    public final void setStatus(@NonNull PrintJobId printJobId, @Nullable CharSequence status) {
314b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        throwIfCalledOnMainThread();
315b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        synchronized (mLock) {
316b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            throwIfDestroyedLocked();
317b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            mCanUnbind = false;
318b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        }
319b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        try {
320b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            getRemoteInstanceLazy().setStatus(printJobId, status);
321b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        } catch (RemoteException|TimeoutException re) {
322b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            Slog.e(LOG_TAG, "Error setting status.", re);
323b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        } finally {
324b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            if (DEBUG) {
325b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setStatus()");
326d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann            }
327d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann            synchronized (mLock) {
328d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann                mCanUnbind = true;
329d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann                mLock.notifyAll();
330d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann            }
331d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann        }
332d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann    }
333d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann
334d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann    /**
335d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann     * Set status of a print job.
336d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann     *
337d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann     * @param printJobId The print job to update
338d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann     * @param status The new status as a string resource
339d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann     * @param appPackageName The app package name the string res belongs to
340d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann     */
341d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann    public final void setStatus(@NonNull PrintJobId printJobId, @StringRes int status,
342d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann            @NonNull CharSequence appPackageName) {
343d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann        throwIfCalledOnMainThread();
344d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann        synchronized (mLock) {
345d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann            throwIfDestroyedLocked();
346d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann            mCanUnbind = false;
347d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann        }
348d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann        try {
349d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann            getRemoteInstanceLazy().setStatusRes(printJobId, status, appPackageName);
350d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann        } catch (RemoteException|TimeoutException re) {
351d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann            Slog.e(LOG_TAG, "Error setting status.", re);
352d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann        } finally {
353d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann            if (DEBUG) {
354d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setStatus()");
355b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            }
356b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            synchronized (mLock) {
357b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann                mCanUnbind = true;
358b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann                mLock.notifyAll();
359b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            }
360b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        }
361b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann    }
362b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann
363bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    /**
364bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     * Handle that a custom icon for a printer was loaded.
365bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     *
366bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     * @param printerId the id of the printer the icon belongs to
367bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     * @param icon the icon that was loaded
368bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     * @see android.print.PrinterInfo.Builder#setHasCustomPrinterIcon()
369bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     */
370bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    public final void onCustomPrinterIconLoaded(@NonNull PrinterId printerId,
371bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            @Nullable Icon icon) {
372bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        throwIfCalledOnMainThread();
373bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        synchronized (mLock) {
374bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            throwIfDestroyedLocked();
375bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            mCanUnbind = false;
376bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
377bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        try {
378bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            mCustomPrinterIconLoadedCaller.onCustomPrinterIconLoaded(getRemoteInstanceLazy(),
379bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                    printerId, icon);
380bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        } catch (RemoteException|TimeoutException re) {
381bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            Slog.e(LOG_TAG, "Error loading new custom printer icon.", re);
382bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        } finally {
383bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            if (DEBUG) {
384bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                Slog.i(LOG_TAG,
385bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                        "[user: " + mUserHandle.getIdentifier() + "] onCustomPrinterIconLoaded()");
386bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            }
387bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            synchronized (mLock) {
388bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                mCanUnbind = true;
389bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                mLock.notifyAll();
390bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            }
391bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
392bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    }
393bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
394bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    /**
395bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     * Get the custom icon for a printer. If the icon is not cached, the icon is
396bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     * requested asynchronously. Once it is available the printer is updated.
397bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     *
398bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     * @param printerId the id of the printer the icon should be loaded for
399bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     * @return the custom icon to be used for the printer or null if the icon is
400bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     *         not yet available
401bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     * @see android.print.PrinterInfo.Builder#setHasCustomPrinterIcon()
402bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     */
403bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    public final @Nullable Icon getCustomPrinterIcon(@NonNull PrinterId printerId) {
404bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        throwIfCalledOnMainThread();
405bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        synchronized (mLock) {
406bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            throwIfDestroyedLocked();
407bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            mCanUnbind = false;
408bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
409bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        try {
410bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            return mGetCustomPrinterIconCaller.getCustomPrinterIcon(getRemoteInstanceLazy(),
411bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                    printerId);
412bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        } catch (RemoteException|TimeoutException re) {
413bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            Slog.e(LOG_TAG, "Error getting custom printer icon.", re);
414bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            return null;
415bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        } finally {
416bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            if (DEBUG) {
417bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                Slog.i(LOG_TAG,
418bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                        "[user: " + mUserHandle.getIdentifier() + "] getCustomPrinterIcon()");
419bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            }
420bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            synchronized (mLock) {
421bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                mCanUnbind = true;
422bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                mLock.notifyAll();
423bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            }
424bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
425bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    }
426bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
427bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    /**
428bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     * Clear the custom printer icon cache
429bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     */
430bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    public void clearCustomPrinterIconCache() {
431bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        throwIfCalledOnMainThread();
432bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        synchronized (mLock) {
433bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            throwIfDestroyedLocked();
434bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            mCanUnbind = false;
435bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
436bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        try {
437bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            mClearCustomPrinterIconCache.clearCustomPrinterIconCache(getRemoteInstanceLazy());
438bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        } catch (RemoteException|TimeoutException re) {
439bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            Slog.e(LOG_TAG, "Error clearing custom printer icon cache.", re);
440bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        } finally {
441bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            if (DEBUG) {
442bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                Slog.i(LOG_TAG,
443bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                        "[user: " + mUserHandle.getIdentifier()
444bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                                + "] clearCustomPrinterIconCache()");
445bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            }
446bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            synchronized (mLock) {
447bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                mCanUnbind = true;
448bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                mLock.notifyAll();
449bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            }
450bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
451bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    }
452bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
4532fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    public final boolean setPrintJobTag(PrintJobId printJobId, String tag) {
454a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        throwIfCalledOnMainThread();
455a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        synchronized (mLock) {
456a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            throwIfDestroyedLocked();
45785b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            mCanUnbind = false;
458a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
459a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        try {
460a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            return mSetPrintJobTagCaller.setPrintJobTag(getRemoteInstanceLazy(),
461a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    printJobId, tag);
462a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        } catch (RemoteException re) {
463a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            Slog.e(LOG_TAG, "Error setting print job tag.", re);
464a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        } catch (TimeoutException te) {
465a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            Slog.e(LOG_TAG, "Error setting print job tag.", te);
46685b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov        } finally {
467835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            if (DEBUG) {
468835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setPrintJobTag()");
469835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            }
47085b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            synchronized (mLock) {
47185b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mCanUnbind = true;
47285b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mLock.notifyAll();
47385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            }
474a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
475a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        return false;
476a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
477a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
478a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov    public final void setPrintJobCancelling(PrintJobId printJobId, boolean cancelling) {
479a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        throwIfCalledOnMainThread();
480a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        synchronized (mLock) {
481a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            throwIfDestroyedLocked();
482a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            mCanUnbind = false;
483a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        }
484a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        try {
485a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            getRemoteInstanceLazy().setPrintJobCancelling(printJobId,
486a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                    cancelling);
487a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        } catch (RemoteException re) {
488a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            Slog.e(LOG_TAG, "Error setting print job cancelling.", re);
489a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        } catch (TimeoutException te) {
490a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            Slog.e(LOG_TAG, "Error setting print job cancelling.", te);
491a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        } finally {
492a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            if (DEBUG) {
493a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
494a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                        + "] setPrintJobCancelling()");
495a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            }
496a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            synchronized (mLock) {
497a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                mCanUnbind = true;
498a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                mLock.notifyAll();
499853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann            }
500853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann        }
501853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann    }
502853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann
503853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann    /**
5048141bdfa56f13c3946bed12ba7801e492ec25c11Philip P. Moltmann     * Remove all approved {@link PrintService print services} that are not in the given set.
505853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann     *
5068141bdfa56f13c3946bed12ba7801e492ec25c11Philip P. Moltmann     * @param servicesToKeep The {@link ComponentName names } of the services to keep
507853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann     */
5088141bdfa56f13c3946bed12ba7801e492ec25c11Philip P. Moltmann    public final void pruneApprovedPrintServices(List<ComponentName> servicesToKeep) {
509853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann        throwIfCalledOnMainThread();
510853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann        synchronized (mLock) {
511853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann            throwIfDestroyedLocked();
512853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann            mCanUnbind = false;
513853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann        }
514853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann        try {
5158141bdfa56f13c3946bed12ba7801e492ec25c11Philip P. Moltmann            getRemoteInstanceLazy().pruneApprovedPrintServices(servicesToKeep);
5168141bdfa56f13c3946bed12ba7801e492ec25c11Philip P. Moltmann        } catch (RemoteException|TimeoutException re) {
5178141bdfa56f13c3946bed12ba7801e492ec25c11Philip P. Moltmann            Slog.e(LOG_TAG, "Error pruning approved print services.", re);
518853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann        } finally {
519853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann            if (DEBUG) {
520853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
5218141bdfa56f13c3946bed12ba7801e492ec25c11Philip P. Moltmann                        + "] pruneApprovedPrintServices()");
522853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann            }
523853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann            synchronized (mLock) {
524853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann                mCanUnbind = true;
525853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann                mLock.notifyAll();
526a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            }
527a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        }
528a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov    }
529a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov
5302fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    public final void removeObsoletePrintJobs() {
5312fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        throwIfCalledOnMainThread();
5322fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        synchronized (mLock) {
5332fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            throwIfDestroyedLocked();
5342fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            mCanUnbind = false;
5352fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        }
5362fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        try {
5372fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            getRemoteInstanceLazy().removeObsoletePrintJobs();
5382fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        } catch (RemoteException re) {
5392fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            Slog.e(LOG_TAG, "Error removing obsolete print jobs .", re);
5402fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        } catch (TimeoutException te) {
5412fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            Slog.e(LOG_TAG, "Error removing obsolete print jobs .", te);
5422fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        } finally {
5432fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            if (DEBUG) {
5442fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
5452fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                        + "] removeObsoletePrintJobs()");
5462fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            }
5472fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            synchronized (mLock) {
5482fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                mCanUnbind = true;
5492fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                mLock.notifyAll();
5502fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            }
5512fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        }
5522fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    }
5532fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav
554a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    public final void destroy() {
555a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        throwIfCalledOnMainThread();
556a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        if (DEBUG) {
557a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] destroy()");
558a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
559a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        synchronized (mLock) {
560a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            throwIfDestroyedLocked();
561a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            unbindLocked();
562a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            mDestroyed = true;
56385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            mCanUnbind = false;
564a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
565a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
566a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
567b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov    public void dump(FileDescriptor fd, PrintWriter pw, String prefix) {
568b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov        synchronized (mLock) {
569b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov            pw.append(prefix).append("destroyed=")
570b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov                    .append(String.valueOf(mDestroyed)).println();
571b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov            pw.append(prefix).append("bound=")
572b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov                    .append((mRemoteInstance != null) ? "true" : "false").println();
573dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov
574dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            pw.flush();
575dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov
576dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            try {
577dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                getRemoteInstanceLazy().asBinder().dump(fd, new String[]{prefix});
578dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            } catch (TimeoutException te) {
579dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                /* ignore */
580dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            } catch (RemoteException re) {
581dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                /* ignore */
582b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov            }
583b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov        }
584b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov    }
585b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov
586a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private void onAllPrintJobsHandled() {
587a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        synchronized (mLock) {
588a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            throwIfDestroyedLocked();
589a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            unbindLocked();
590a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
591a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
592a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
593dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov    private void onPrintJobStateChanged(PrintJobInfo printJob) {
594dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov        mCallbacks.onPrintJobStateChanged(printJob);
595704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov    }
596704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov
597a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private IPrintSpooler getRemoteInstanceLazy() throws TimeoutException {
598a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        synchronized (mLock) {
599a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            if (mRemoteInstance != null) {
600a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                return mRemoteInstance;
601a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            }
602a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            bindLocked();
603a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            return mRemoteInstance;
604a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
605a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
606a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
607a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private void bindLocked() throws TimeoutException {
6082fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        if (mRemoteInstance != null) {
6092fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            return;
6102fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        }
611a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        if (DEBUG) {
612e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann            Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] bindLocked() " +
613e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                    (mIsLowPriority ? "low priority" : ""));
614e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann        }
615e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann
616e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann        int flags;
617e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann        if (mIsLowPriority) {
618e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann            flags = Context.BIND_AUTO_CREATE;
619e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann        } else {
620e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann            flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE;
621a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
622a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
623e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann        mContext.bindServiceAsUser(mIntent, mServiceConnection, flags, mUserHandle);
624a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
625a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        final long startMillis = SystemClock.uptimeMillis();
626a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        while (true) {
627a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            if (mRemoteInstance != null) {
628a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                break;
629a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            }
630a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
631a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            final long remainingMillis = BIND_SPOOLER_SERVICE_TIMEOUT - elapsedMillis;
632a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            if (remainingMillis <= 0) {
633a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                throw new TimeoutException("Cannot get spooler!");
634a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            }
635a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            try {
636a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                mLock.wait(remainingMillis);
637a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            } catch (InterruptedException ie) {
638a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                /* ignore */
639a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            }
640a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
64185b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov
64285b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov        mCanUnbind = true;
64385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov        mLock.notifyAll();
644a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
645a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
646a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private void unbindLocked() {
6472fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        if (mRemoteInstance == null) {
6482fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            return;
6492fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        }
65085b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov        while (true) {
65185b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            if (mCanUnbind) {
65285b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                if (DEBUG) {
65385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                    Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] unbindLocked()");
65485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                }
65585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                clearClientLocked();
65685b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mRemoteInstance = null;
65785b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mContext.unbindService(mServiceConnection);
65885b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                return;
65985b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            }
66085b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            try {
66185b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mLock.wait();
66285b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            } catch (InterruptedException ie) {
66385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                /* ignore */
66485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            }
665a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
66685b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov
667a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
668a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
669a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private void setClientLocked() {
670a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        try {
671a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            mRemoteInstance.setClient(mClient);
672a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        } catch (RemoteException re) {
673a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            Slog.d(LOG_TAG, "Error setting print spooler client", re);
674a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
675a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
676a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
677a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private void clearClientLocked() {
678a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        try {
679a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            mRemoteInstance.setClient(null);
680a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        } catch (RemoteException re) {
681a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            Slog.d(LOG_TAG, "Error clearing print spooler client", re);
682a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
683a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
684a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
685a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
686a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private void throwIfDestroyedLocked() {
687a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        if (mDestroyed) {
688a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            throw new IllegalStateException("Cannot interact with a destroyed instance.");
689a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
690a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
691a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
692a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private void throwIfCalledOnMainThread() {
693a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        if (Thread.currentThread() == mContext.getMainLooper().getThread()) {
694a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            throw new RuntimeException("Cannot invoke on the main thread");
695a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
696a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
697a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
698a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final class MyServiceConnection implements ServiceConnection {
699a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        @Override
700a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onServiceConnected(ComponentName name, IBinder service) {
701a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            synchronized (mLock) {
702a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                mRemoteInstance = IPrintSpooler.Stub.asInterface(service);
703a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                setClientLocked();
704a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                mLock.notifyAll();
705a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            }
706a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
707a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
708a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        @Override
709a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onServiceDisconnected(ComponentName name) {
710a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            synchronized (mLock) {
711a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                clearClientLocked();
712a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                mRemoteInstance = null;
713a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            }
714a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
715a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
716a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
717a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private static final class GetPrintJobInfosCaller
718a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            extends TimedRemoteCaller<List<PrintJobInfo>> {
719a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        private final IPrintSpoolerCallbacks mCallback;
720a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
721a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public GetPrintJobInfosCaller() {
722a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS);
723a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            mCallback = new BasePrintSpoolerServiceCallbacks() {
724a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                @Override
725a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                public void onGetPrintJobInfosResult(List<PrintJobInfo> printJobs, int sequence) {
726a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    onRemoteMethodResult(printJobs, sequence);
727a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                }
728a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            };
729a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
730a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
731a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public List<PrintJobInfo> getPrintJobInfos(IPrintSpooler target,
732a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                ComponentName componentName, int state, int appId)
733a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                        throws RemoteException, TimeoutException {
734a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            final int sequence = onBeforeRemoteCall();
735a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            target.getPrintJobInfos(mCallback, componentName, state, appId, sequence);
736a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            return getResultTimed(sequence);
737a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
738a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
739a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
740a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private static final class GetPrintJobInfoCaller extends TimedRemoteCaller<PrintJobInfo> {
741a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        private final IPrintSpoolerCallbacks mCallback;
742a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
743a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public GetPrintJobInfoCaller() {
744a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS);
745a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            mCallback = new BasePrintSpoolerServiceCallbacks() {
746a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                @Override
747a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                public void onGetPrintJobInfoResult(PrintJobInfo printJob, int sequence) {
748a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    onRemoteMethodResult(printJob, sequence);
749a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                }
750a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            };
751a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
752a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
7532fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        public PrintJobInfo getPrintJobInfo(IPrintSpooler target, PrintJobId printJobId,
754a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                int appId) throws RemoteException, TimeoutException {
755a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            final int sequence = onBeforeRemoteCall();
756a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            target.getPrintJobInfo(printJobId, mCallback, appId, sequence);
757a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            return getResultTimed(sequence);
758a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
759a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
760a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
761a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private static final class SetPrintJobStateCaller extends TimedRemoteCaller<Boolean> {
762a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        private final IPrintSpoolerCallbacks mCallback;
763a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
764a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public SetPrintJobStateCaller() {
765a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS);
766a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            mCallback = new BasePrintSpoolerServiceCallbacks() {
767a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                @Override
768a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                public void onSetPrintJobStateResult(boolean success, int sequence) {
769a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    onRemoteMethodResult(success, sequence);
770a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                }
771a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            };
772a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
773a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
7742fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        public boolean setPrintJobState(IPrintSpooler target, PrintJobId printJobId,
775269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                int status, String error) throws RemoteException, TimeoutException {
776a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            final int sequence = onBeforeRemoteCall();
7778c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov            target.setPrintJobState(printJobId, status, error, mCallback, sequence);
778a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            return getResultTimed(sequence);
779a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
780a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
781a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
782a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private static final class SetPrintJobTagCaller extends TimedRemoteCaller<Boolean> {
783a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        private final IPrintSpoolerCallbacks mCallback;
784a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
785a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public SetPrintJobTagCaller() {
786a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS);
787a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            mCallback = new BasePrintSpoolerServiceCallbacks() {
788a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                @Override
789a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                public void onSetPrintJobTagResult(boolean success, int sequence) {
790a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    onRemoteMethodResult(success, sequence);
791a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                }
792a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            };
793a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
794a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
7952fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        public boolean setPrintJobTag(IPrintSpooler target, PrintJobId printJobId,
796a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                String tag) throws RemoteException, TimeoutException {
797a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            final int sequence = onBeforeRemoteCall();
798a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            target.setPrintJobTag(printJobId, tag, mCallback, sequence);
799a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            return getResultTimed(sequence);
800a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
801a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
802a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
803bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    private static final class OnCustomPrinterIconLoadedCaller extends TimedRemoteCaller<Void> {
804bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        private final IPrintSpoolerCallbacks mCallback;
805bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
806bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        public OnCustomPrinterIconLoadedCaller() {
807bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS);
808bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            mCallback = new BasePrintSpoolerServiceCallbacks() {
809bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                @Override
810bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                public void onCustomPrinterIconCached(int sequence) {
811bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                    onRemoteMethodResult(null, sequence);
812bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                }
813bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            };
814bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
815bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
816bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        public Void onCustomPrinterIconLoaded(IPrintSpooler target, PrinterId printerId,
817bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                Icon icon) throws RemoteException, TimeoutException {
818bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            final int sequence = onBeforeRemoteCall();
819bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            target.onCustomPrinterIconLoaded(printerId, icon, mCallback, sequence);
820bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            return getResultTimed(sequence);
821bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
822bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    }
823bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
824bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    private static final class ClearCustomPrinterIconCacheCaller extends TimedRemoteCaller<Void> {
825bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        private final IPrintSpoolerCallbacks mCallback;
826bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
827bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        public ClearCustomPrinterIconCacheCaller() {
828bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS);
829bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            mCallback = new BasePrintSpoolerServiceCallbacks() {
830bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                @Override
831bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                public void customPrinterIconCacheCleared(int sequence) {
832bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                    onRemoteMethodResult(null, sequence);
833bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                }
834bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            };
835bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
836bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
837bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        public Void clearCustomPrinterIconCache(IPrintSpooler target)
838bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                throws RemoteException, TimeoutException {
839bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            final int sequence = onBeforeRemoteCall();
840bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            target.clearCustomPrinterIconCache(mCallback, sequence);
841bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            return getResultTimed(sequence);
842bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
843bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    }
844bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
845bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    private static final class GetCustomPrinterIconCaller extends TimedRemoteCaller<Icon> {
846bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        private final IPrintSpoolerCallbacks mCallback;
847bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
848bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        public GetCustomPrinterIconCaller() {
849bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS);
850bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            mCallback = new BasePrintSpoolerServiceCallbacks() {
851bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                @Override
852bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                public void onGetCustomPrinterIconResult(Icon icon, int sequence) {
853bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                    onRemoteMethodResult(icon, sequence);
854bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                }
855bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            };
856bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
857bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
858bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        public Icon getCustomPrinterIcon(IPrintSpooler target, PrinterId printerId)
859bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                throws RemoteException, TimeoutException {
860bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            final int sequence = onBeforeRemoteCall();
861bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            target.getCustomPrinterIcon(printerId, mCallback, sequence);
862bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            return getResultTimed(sequence);
863bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
864bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    }
865bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
866a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private static abstract class BasePrintSpoolerServiceCallbacks
867a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            extends IPrintSpoolerCallbacks.Stub {
868a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        @Override
869a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onGetPrintJobInfosResult(List<PrintJobInfo> printJobIds, int sequence) {
870a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            /* do nothing */
871a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
872a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
873a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        @Override
874a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onGetPrintJobInfoResult(PrintJobInfo printJob, int sequence) {
875a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            /* do nothing */
876a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
877a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
878a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        @Override
879a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onCancelPrintJobResult(boolean canceled, int sequence) {
880a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            /* do nothing */
881a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
882a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
883a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        @Override
884a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onSetPrintJobStateResult(boolean success, int sequece) {
885a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            /* do nothing */
886a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
887a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
888a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        @Override
889a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onSetPrintJobTagResult(boolean success, int sequence) {
890a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            /* do nothing */
891a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
892bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
893bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        @Override
894bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        public void onCustomPrinterIconCached(int sequence) {
895bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            /* do nothing */
896bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
897bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
898bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        @Override
899bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        public void onGetCustomPrinterIconResult(@Nullable Icon icon, int sequence) {
900bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            /* do nothing */
901bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
902bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
903bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        @Override
904bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        public void customPrinterIconCacheCleared(int sequence) {
905bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            /* do nothing */
906bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
907a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
908a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
909a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private static final class PrintSpoolerClient extends IPrintSpoolerClient.Stub {
910a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
911a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        private final WeakReference<RemotePrintSpooler> mWeakSpooler;
912a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
913a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public PrintSpoolerClient(RemotePrintSpooler spooler) {
914a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            mWeakSpooler = new WeakReference<RemotePrintSpooler>(spooler);
915a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
916a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
917a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        @Override
918a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onPrintJobQueued(PrintJobInfo printJob) {
919a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            RemotePrintSpooler spooler = mWeakSpooler.get();
920a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            if (spooler != null) {
921a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                final long identity = Binder.clearCallingIdentity();
922a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                try {
923a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    spooler.mCallbacks.onPrintJobQueued(printJob);
924a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                } finally {
925a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    Binder.restoreCallingIdentity(identity);
926a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                }
927a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            }
928a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
929a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
930a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        @Override
931a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onAllPrintJobsForServiceHandled(ComponentName printService) {
932a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            RemotePrintSpooler spooler = mWeakSpooler.get();
933a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            if (spooler != null) {
934a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                final long identity = Binder.clearCallingIdentity();
935a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                try {
936a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    spooler.mCallbacks.onAllPrintJobsForServiceHandled(printService);
937a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                } finally {
938a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    Binder.restoreCallingIdentity(identity);
939a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                }
940a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            }
941a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
942a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
943a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        @Override
944a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onAllPrintJobsHandled() {
945a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            RemotePrintSpooler spooler = mWeakSpooler.get();
946a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            if (spooler != null) {
947a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                final long identity = Binder.clearCallingIdentity();
948a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                try {
949a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    spooler.onAllPrintJobsHandled();
950a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                } finally {
951a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    Binder.restoreCallingIdentity(identity);
952a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                }
953a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            }
954a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
955704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov
956704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        @Override
957dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov        public void onPrintJobStateChanged(PrintJobInfo printJob) {
958704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            RemotePrintSpooler spooler = mWeakSpooler.get();
959704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            if (spooler != null) {
960704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                final long identity = Binder.clearCallingIdentity();
961704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                try {
962dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                    spooler.onPrintJobStateChanged(printJob);
963704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                } finally {
964704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                    Binder.restoreCallingIdentity(identity);
965704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                }
966704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            }
967704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        }
968a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
969a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov}
970