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
4693a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmannimport com.android.internal.annotations.GuardedBy;
47850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkeyimport com.android.internal.os.TransferPipe;
48850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey
498141bdfa56f13c3946bed12ba7801e492ec25c11Philip P. Moltmannimport libcore.io.IoUtils;
508141bdfa56f13c3946bed12ba7801e492ec25c11Philip P. Moltmann
51b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganovimport java.io.FileDescriptor;
52850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkeyimport java.io.IOException;
53b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganovimport java.io.PrintWriter;
54a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport java.lang.ref.WeakReference;
55a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport java.util.List;
56a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport java.util.concurrent.TimeoutException;
57a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
58a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov/**
59a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * This represents the remote print spooler as a local object to the
60a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * PrintManagerService. It is responsible to connecting to the remote
61a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * spooler if needed, to make the timed remote calls, to handle
62a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * remote exceptions, and to bind/unbind to the remote instance as
63a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * needed.
64e2ad85d230392e18013bc50f37b46268aa4245a6Philip P. Moltmann *
65e2ad85d230392e18013bc50f37b46268aa4245a6Philip P. Moltmann * The calls might be blocking and need the main thread of to be unblocked to finish. Hence do not
66e2ad85d230392e18013bc50f37b46268aa4245a6Philip P. Moltmann * call this while holding any monitors that might need to be acquired the main thread.
67a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov */
68a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovfinal class RemotePrintSpooler {
69a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
70a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private static final String LOG_TAG = "RemotePrintSpooler";
71a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
72c6066799ad130140159230d14451b429eb828755Svetoslav    private static final boolean DEBUG = false;
73a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
74f983d084e7b8a6de722d9cede1c0cf73831c8e92Svet Ganov    private static final long BIND_SPOOLER_SERVICE_TIMEOUT =
75f983d084e7b8a6de722d9cede1c0cf73831c8e92Svet Ganov            ("eng".equals(Build.TYPE)) ? 120000 : 10000;
76a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
77a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final Object mLock = new Object();
78a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
79a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final GetPrintJobInfosCaller mGetPrintJobInfosCaller = new GetPrintJobInfosCaller();
80a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
81a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final GetPrintJobInfoCaller mGetPrintJobInfoCaller = new GetPrintJobInfoCaller();
82a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
83a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final SetPrintJobStateCaller mSetPrintJobStatusCaller = new SetPrintJobStateCaller();
84a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
85a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final SetPrintJobTagCaller mSetPrintJobTagCaller = new SetPrintJobTagCaller();
86a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
87bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    private final OnCustomPrinterIconLoadedCaller mCustomPrinterIconLoadedCaller =
88bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            new OnCustomPrinterIconLoadedCaller();
89bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
90bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    private final ClearCustomPrinterIconCacheCaller mClearCustomPrinterIconCache =
91bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            new ClearCustomPrinterIconCacheCaller();
92bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
93bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    private final GetCustomPrinterIconCaller mGetCustomPrinterIconCaller =
94bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            new GetCustomPrinterIconCaller();
95bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
96a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final ServiceConnection mServiceConnection = new MyServiceConnection();
97a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
98a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final Context mContext;
99a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
100a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final UserHandle mUserHandle;
101a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
102a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final PrintSpoolerClient mClient;
103a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
104a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final Intent mIntent;
105a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
106a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final PrintSpoolerCallbacks mCallbacks;
107a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
108e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann    private boolean mIsLowPriority;
109e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann
110a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private IPrintSpooler mRemoteInstance;
111a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
112a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private boolean mDestroyed;
113a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
11485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov    private boolean mCanUnbind;
11585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov
11693a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann    /** Whether a thread is currently trying to {@link #bindLocked() bind to the print service} */
11793a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann    @GuardedBy("mLock")
11893a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann    private boolean mIsBinding;
11993a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann
120a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    public static interface PrintSpoolerCallbacks {
121a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onPrintJobQueued(PrintJobInfo printJob);
122a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onAllPrintJobsForServiceHandled(ComponentName printService);
123dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov        public void onPrintJobStateChanged(PrintJobInfo printJob);
124a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
125a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
126e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann    public RemotePrintSpooler(Context context, int userId, boolean lowPriority,
127a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            PrintSpoolerCallbacks callbacks) {
128a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        mContext = context;
129a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        mUserHandle = new UserHandle(userId);
130a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        mCallbacks = callbacks;
131e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann        mIsLowPriority = lowPriority;
132a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        mClient = new PrintSpoolerClient(this);
133a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        mIntent = new Intent();
13466c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann        mIntent.setComponent(new ComponentName(PrintManager.PRINT_SPOOLER_PACKAGE_NAME,
13566c96591e2ddb464c67e60dbf4193ef4ec8a620bPhilip P. Moltmann                PrintManager.PRINT_SPOOLER_PACKAGE_NAME + ".model.PrintSpoolerService"));
136a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
137a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
138e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann    public void increasePriority() {
139e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann        if (mIsLowPriority) {
140e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann            mIsLowPriority = false;
141e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann
142e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann            synchronized (mLock) {
143e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                throwIfDestroyedLocked();
144e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann
145e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                while (!mCanUnbind) {
146e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                    try {
147e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                        mLock.wait();
148e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                    } catch (InterruptedException e) {
149e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                        Slog.e(LOG_TAG, "Interrupted while waiting for operation to complete");
150e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                    }
151e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                }
152e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann
153e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                if (DEBUG) {
154e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                    Slog.i(LOG_TAG, "Unbinding as previous binding was low priority");
155e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                }
156e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann
157e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                unbindLocked();
158e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann            }
159e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann        }
160e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann    }
161e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann
162a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    public final List<PrintJobInfo> getPrintJobInfos(ComponentName componentName, int state,
163a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            int appId) {
164a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        throwIfCalledOnMainThread();
165a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        synchronized (mLock) {
166a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            throwIfDestroyedLocked();
16785b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            mCanUnbind = false;
168a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
169a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        try {
170a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            return mGetPrintJobInfosCaller.getPrintJobInfos(getRemoteInstanceLazy(),
171a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    componentName, state, appId);
17293a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann        } catch (RemoteException | TimeoutException | InterruptedException e) {
17393a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            Slog.e(LOG_TAG, "Error getting print jobs.", e);
17485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov        } finally {
175835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            if (DEBUG) {
176835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] getPrintJobInfos()");
177835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            }
17885b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            synchronized (mLock) {
17985b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mCanUnbind = true;
18085b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mLock.notifyAll();
18185b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            }
182a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
183a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        return null;
184a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
185a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
1867bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav    public final void createPrintJob(PrintJobInfo printJob) {
187a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        throwIfCalledOnMainThread();
188a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        synchronized (mLock) {
189a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            throwIfDestroyedLocked();
19085b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            mCanUnbind = false;
191a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
192a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        try {
1937bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav            getRemoteInstanceLazy().createPrintJob(printJob);
19493a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann        } catch (RemoteException | TimeoutException | InterruptedException e) {
19593a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            Slog.e(LOG_TAG, "Error creating print job.", e);
19685b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov        } finally {
197835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            if (DEBUG) {
198835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] createPrintJob()");
199835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            }
20085b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            synchronized (mLock) {
20185b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mCanUnbind = true;
20285b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mLock.notifyAll();
20385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            }
204a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
205a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
206a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
2072fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    public final void writePrintJobData(ParcelFileDescriptor fd, PrintJobId printJobId) {
208a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        throwIfCalledOnMainThread();
209a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        synchronized (mLock) {
210a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            throwIfDestroyedLocked();
21185b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            mCanUnbind = false;
212a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
213a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        try {
214a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            getRemoteInstanceLazy().writePrintJobData(fd, printJobId);
21593a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann        } catch (RemoteException | TimeoutException | InterruptedException e) {
21693a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            Slog.e(LOG_TAG, "Error writing print job data.", e);
217a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        } finally {
218835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            if (DEBUG) {
219835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] writePrintJobData()");
220835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            }
221a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            // We passed the file descriptor across and now the other
222a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            // side is responsible to close it, so close the local copy.
223a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            IoUtils.closeQuietly(fd);
22485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            synchronized (mLock) {
22585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mCanUnbind = true;
22685b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mLock.notifyAll();
22785b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            }
228a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
229a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
230a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
2312fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    public final PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId) {
232a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        throwIfCalledOnMainThread();
233a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        synchronized (mLock) {
234a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            throwIfDestroyedLocked();
23585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            mCanUnbind = false;
236a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
237a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        try {
238a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            return mGetPrintJobInfoCaller.getPrintJobInfo(getRemoteInstanceLazy(),
239a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    printJobId, appId);
24093a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann        } catch (RemoteException | TimeoutException | InterruptedException e) {
24193a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            Slog.e(LOG_TAG, "Error getting print job info.", e);
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);
26393a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann        } catch (RemoteException | TimeoutException | InterruptedException e) {
26493a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            Slog.e(LOG_TAG, "Error setting print job state.", e);
26585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov        } finally {
266835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            if (DEBUG) {
267835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setPrintJobState()");
268835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            }
26985b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            synchronized (mLock) {
27085b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mCanUnbind = true;
27185b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mLock.notifyAll();
27285b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            }
273a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
274a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        return false;
275a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
276a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
277b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann    /**
278b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann     * Set progress of a print job.
279b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann     *
280b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann     * @param printJobId The print job to update
281b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann     * @param progress The new progress
282b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann     */
283b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann    public final void setProgress(@NonNull PrintJobId printJobId,
284b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            @FloatRange(from=0.0, to=1.0) float progress) {
285b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        throwIfCalledOnMainThread();
286b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        synchronized (mLock) {
287b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            throwIfDestroyedLocked();
288b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            mCanUnbind = false;
289b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        }
290b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        try {
291b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            getRemoteInstanceLazy().setProgress(printJobId, progress);
29293a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann        } catch (RemoteException | TimeoutException | InterruptedException re) {
293b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            Slog.e(LOG_TAG, "Error setting progress.", re);
294b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        } finally {
295b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            if (DEBUG) {
296b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setProgress()");
297b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            }
298b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            synchronized (mLock) {
299b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann                mCanUnbind = true;
300b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann                mLock.notifyAll();
301b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            }
302b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        }
303b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann    }
304b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann
305b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann    /**
306b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann     * Set status of a print job.
307b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann     *
308b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann     * @param printJobId The print job to update
309b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann     * @param status The new status
310b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann     */
311b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann    public final void setStatus(@NonNull PrintJobId printJobId, @Nullable CharSequence status) {
312b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        throwIfCalledOnMainThread();
313b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        synchronized (mLock) {
314b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            throwIfDestroyedLocked();
315b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            mCanUnbind = false;
316b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        }
317b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        try {
318b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            getRemoteInstanceLazy().setStatus(printJobId, status);
31993a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann        } catch (RemoteException | TimeoutException | InterruptedException e) {
32093a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            Slog.e(LOG_TAG, "Error setting status.", e);
321b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        } finally {
322b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            if (DEBUG) {
323b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setStatus()");
324d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann            }
325d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann            synchronized (mLock) {
326d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann                mCanUnbind = true;
327d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann                mLock.notifyAll();
328d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann            }
329d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann        }
330d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann    }
331d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann
332d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann    /**
333d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann     * Set status of a print job.
334d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann     *
335d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann     * @param printJobId The print job to update
336d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann     * @param status The new status as a string resource
337d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann     * @param appPackageName The app package name the string res belongs to
338d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann     */
339d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann    public final void setStatus(@NonNull PrintJobId printJobId, @StringRes int status,
340d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann            @NonNull CharSequence appPackageName) {
341d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann        throwIfCalledOnMainThread();
342d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann        synchronized (mLock) {
343d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann            throwIfDestroyedLocked();
344d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann            mCanUnbind = false;
345d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann        }
346d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann        try {
347d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann            getRemoteInstanceLazy().setStatusRes(printJobId, status, appPackageName);
34893a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann        } catch (RemoteException | TimeoutException | InterruptedException e) {
34993a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            Slog.e(LOG_TAG, "Error setting status.", e);
350d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann        } finally {
351d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann            if (DEBUG) {
352d74d1e549168ba521e8009961b76e8718be37aa1Philip P. Moltmann                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setStatus()");
353b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            }
354b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            synchronized (mLock) {
355b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann                mCanUnbind = true;
356b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann                mLock.notifyAll();
357b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann            }
358b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann        }
359b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann    }
360b3078c235e7674fd61be75fb469105ba6174aba5Philip P. Moltmann
361bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    /**
362bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     * Handle that a custom icon for a printer was loaded.
363bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     *
364bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     * @param printerId the id of the printer the icon belongs to
365bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     * @param icon the icon that was loaded
366bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     * @see android.print.PrinterInfo.Builder#setHasCustomPrinterIcon()
367bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     */
368bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    public final void onCustomPrinterIconLoaded(@NonNull PrinterId printerId,
369bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            @Nullable Icon icon) {
370bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        throwIfCalledOnMainThread();
371bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        synchronized (mLock) {
372bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            throwIfDestroyedLocked();
373bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            mCanUnbind = false;
374bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
375bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        try {
376bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            mCustomPrinterIconLoadedCaller.onCustomPrinterIconLoaded(getRemoteInstanceLazy(),
377bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                    printerId, icon);
37893a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann        } catch (RemoteException | TimeoutException | InterruptedException re) {
379bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            Slog.e(LOG_TAG, "Error loading new custom printer icon.", re);
380bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        } finally {
381bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            if (DEBUG) {
382bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                Slog.i(LOG_TAG,
383bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                        "[user: " + mUserHandle.getIdentifier() + "] onCustomPrinterIconLoaded()");
384bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            }
385bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            synchronized (mLock) {
386bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                mCanUnbind = true;
387bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                mLock.notifyAll();
388bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            }
389bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
390bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    }
391bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
392bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    /**
393bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     * Get the custom icon for a printer. If the icon is not cached, the icon is
394bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     * requested asynchronously. Once it is available the printer is updated.
395bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     *
396bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     * @param printerId the id of the printer the icon should be loaded for
397bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     * @return the custom icon to be used for the printer or null if the icon is
398bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     *         not yet available
399bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     * @see android.print.PrinterInfo.Builder#setHasCustomPrinterIcon()
400bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     */
401bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    public final @Nullable Icon getCustomPrinterIcon(@NonNull PrinterId printerId) {
402bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        throwIfCalledOnMainThread();
403bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        synchronized (mLock) {
404bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            throwIfDestroyedLocked();
405bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            mCanUnbind = false;
406bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
407bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        try {
408bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            return mGetCustomPrinterIconCaller.getCustomPrinterIcon(getRemoteInstanceLazy(),
409bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                    printerId);
41093a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann        } catch (RemoteException | TimeoutException | InterruptedException e) {
41193a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            Slog.e(LOG_TAG, "Error getting custom printer icon.", e);
412bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            return null;
413bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        } finally {
414bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            if (DEBUG) {
415bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                Slog.i(LOG_TAG,
416bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                        "[user: " + mUserHandle.getIdentifier() + "] getCustomPrinterIcon()");
417bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            }
418bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            synchronized (mLock) {
419bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                mCanUnbind = true;
420bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                mLock.notifyAll();
421bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            }
422bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
423bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    }
424bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
425bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    /**
426bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     * Clear the custom printer icon cache
427bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann     */
428bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    public void clearCustomPrinterIconCache() {
429bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        throwIfCalledOnMainThread();
430bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        synchronized (mLock) {
431bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            throwIfDestroyedLocked();
432bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            mCanUnbind = false;
433bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
434bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        try {
435bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            mClearCustomPrinterIconCache.clearCustomPrinterIconCache(getRemoteInstanceLazy());
43693a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann        } catch (RemoteException | TimeoutException | InterruptedException e) {
43793a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            Slog.e(LOG_TAG, "Error clearing custom printer icon cache.", e);
438bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        } finally {
439bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            if (DEBUG) {
440bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                Slog.i(LOG_TAG,
441bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                        "[user: " + mUserHandle.getIdentifier()
442bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                                + "] clearCustomPrinterIconCache()");
443bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            }
444bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            synchronized (mLock) {
445bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                mCanUnbind = true;
446bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                mLock.notifyAll();
447bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            }
448bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
449bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    }
450bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
4512fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    public final boolean setPrintJobTag(PrintJobId printJobId, String tag) {
452a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        throwIfCalledOnMainThread();
453a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        synchronized (mLock) {
454a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            throwIfDestroyedLocked();
45585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            mCanUnbind = false;
456a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
457a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        try {
458a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            return mSetPrintJobTagCaller.setPrintJobTag(getRemoteInstanceLazy(),
459a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    printJobId, tag);
46093a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann        } catch (RemoteException | TimeoutException | InterruptedException e) {
46193a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            Slog.e(LOG_TAG, "Error setting print job tag.", e);
46285b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov        } finally {
463835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            if (DEBUG) {
464835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setPrintJobTag()");
465835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov            }
46685b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            synchronized (mLock) {
46785b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mCanUnbind = true;
46885b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mLock.notifyAll();
46985b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            }
470a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
471a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        return false;
472a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
473a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
474a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov    public final void setPrintJobCancelling(PrintJobId printJobId, boolean cancelling) {
475a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        throwIfCalledOnMainThread();
476a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        synchronized (mLock) {
477a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            throwIfDestroyedLocked();
478a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            mCanUnbind = false;
479a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        }
480a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        try {
481a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            getRemoteInstanceLazy().setPrintJobCancelling(printJobId,
482a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                    cancelling);
48393a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann        } catch (RemoteException | TimeoutException | InterruptedException e) {
48493a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            Slog.e(LOG_TAG, "Error setting print job cancelling.", e);
485a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        } finally {
486a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            if (DEBUG) {
487a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
488a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                        + "] setPrintJobCancelling()");
489a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            }
490a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            synchronized (mLock) {
491a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                mCanUnbind = true;
492a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov                mLock.notifyAll();
493853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann            }
494853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann        }
495853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann    }
496853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann
497853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann    /**
4988141bdfa56f13c3946bed12ba7801e492ec25c11Philip P. Moltmann     * Remove all approved {@link PrintService print services} that are not in the given set.
499853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann     *
5008141bdfa56f13c3946bed12ba7801e492ec25c11Philip P. Moltmann     * @param servicesToKeep The {@link ComponentName names } of the services to keep
501853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann     */
5028141bdfa56f13c3946bed12ba7801e492ec25c11Philip P. Moltmann    public final void pruneApprovedPrintServices(List<ComponentName> servicesToKeep) {
503853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann        throwIfCalledOnMainThread();
504853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann        synchronized (mLock) {
505853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann            throwIfDestroyedLocked();
506853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann            mCanUnbind = false;
507853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann        }
508853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann        try {
5098141bdfa56f13c3946bed12ba7801e492ec25c11Philip P. Moltmann            getRemoteInstanceLazy().pruneApprovedPrintServices(servicesToKeep);
51093a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann        } catch (RemoteException | TimeoutException | InterruptedException e) {
51193a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            Slog.e(LOG_TAG, "Error pruning approved print services.", e);
512853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann        } finally {
513853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann            if (DEBUG) {
514853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
5158141bdfa56f13c3946bed12ba7801e492ec25c11Philip P. Moltmann                        + "] pruneApprovedPrintServices()");
516853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann            }
517853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann            synchronized (mLock) {
518853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann                mCanUnbind = true;
519853a6f564abaf8acbd88c6704008c5d150d00471Philip P. Moltmann                mLock.notifyAll();
520a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov            }
521a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov        }
522a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov    }
523a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov
5242fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    public final void removeObsoletePrintJobs() {
5252fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        throwIfCalledOnMainThread();
5262fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        synchronized (mLock) {
5272fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            throwIfDestroyedLocked();
5282fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            mCanUnbind = false;
5292fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        }
5302fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        try {
5312fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            getRemoteInstanceLazy().removeObsoletePrintJobs();
53293a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann        } catch (RemoteException | TimeoutException | InterruptedException te) {
5332fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            Slog.e(LOG_TAG, "Error removing obsolete print jobs .", te);
5342fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        } finally {
5352fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            if (DEBUG) {
5362fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
5372fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                        + "] removeObsoletePrintJobs()");
5382fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            }
5392fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            synchronized (mLock) {
5402fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                mCanUnbind = true;
5412fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav                mLock.notifyAll();
5422fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            }
5432fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        }
5442fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav    }
5452fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav
546a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    public final void destroy() {
547a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        throwIfCalledOnMainThread();
548a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        if (DEBUG) {
549a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] destroy()");
550a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
551a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        synchronized (mLock) {
552a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            throwIfDestroyedLocked();
553a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            unbindLocked();
554a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            mDestroyed = true;
55585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            mCanUnbind = false;
556a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
557a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
558a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
559b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov    public void dump(FileDescriptor fd, PrintWriter pw, String prefix) {
560b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov        synchronized (mLock) {
561b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov            pw.append(prefix).append("destroyed=")
562b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov                    .append(String.valueOf(mDestroyed)).println();
563b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov            pw.append(prefix).append("bound=")
564b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov                    .append((mRemoteInstance != null) ? "true" : "false").println();
565dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov
566dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            pw.flush();
567dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov            try {
568850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey                TransferPipe.dumpAsync(getRemoteInstanceLazy().asBinder(), fd,
569850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey                        new String[] { prefix });
57093a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            } catch (IOException | TimeoutException | RemoteException | InterruptedException e) {
571850c83e6da3b34a4eab804133420247fc9dbb8a1Jeff Sharkey                pw.println("Failed to dump remote instance: " + e);
572b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov            }
573b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov        }
574b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov    }
575b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov
576a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private void onAllPrintJobsHandled() {
577a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        synchronized (mLock) {
578a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            throwIfDestroyedLocked();
579a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            unbindLocked();
580a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
581a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
582a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
583dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov    private void onPrintJobStateChanged(PrintJobInfo printJob) {
584dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov        mCallbacks.onPrintJobStateChanged(printJob);
585704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov    }
586704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov
58793a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann    private IPrintSpooler getRemoteInstanceLazy() throws TimeoutException, InterruptedException {
588a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        synchronized (mLock) {
589a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            if (mRemoteInstance != null) {
590a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                return mRemoteInstance;
591a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            }
592a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            bindLocked();
593a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            return mRemoteInstance;
594a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
595a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
596a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
59793a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann    private void bindLocked() throws TimeoutException, InterruptedException {
59893a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann        while (mIsBinding) {
59993a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            mLock.wait();
60093a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann        }
60193a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann
6022fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        if (mRemoteInstance != null) {
6032fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            return;
6042fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        }
60593a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann
60693a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann        mIsBinding = true;
60793a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann
608a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        if (DEBUG) {
609e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann            Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] bindLocked() " +
610e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann                    (mIsLowPriority ? "low priority" : ""));
611e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann        }
612e8ae15482eef7617494cb3187899983e27cb8a35Philip P. Moltmann
61393a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann        try {
61493a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            int flags;
61593a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            if (mIsLowPriority) {
61693a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann                flags = Context.BIND_AUTO_CREATE;
61793a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            } else {
61893a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann                flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE;
61993a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            }
620a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
62193a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            mContext.bindServiceAsUser(mIntent, mServiceConnection, flags, mUserHandle);
622a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
62393a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            final long startMillis = SystemClock.uptimeMillis();
62493a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            while (true) {
62593a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann                if (mRemoteInstance != null) {
62693a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann                    break;
62793a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann                }
62893a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann                final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
62993a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann                final long remainingMillis = BIND_SPOOLER_SERVICE_TIMEOUT - elapsedMillis;
63093a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann                if (remainingMillis <= 0) {
63193a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann                    throw new TimeoutException("Cannot get spooler!");
63293a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann                }
633a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                mLock.wait(remainingMillis);
634a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            }
63585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov
63693a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            mCanUnbind = true;
63793a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann        } finally {
63893a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            mIsBinding = false;
63993a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann            mLock.notifyAll();
64093a224936945d1fd773c761279b8949d30325bacPhilip P. Moltmann        }
641a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
642a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
643a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private void unbindLocked() {
6442fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        if (mRemoteInstance == null) {
6452fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav            return;
6462fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        }
64785b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov        while (true) {
64885b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            if (mCanUnbind) {
64985b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                if (DEBUG) {
65085b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                    Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] unbindLocked()");
65185b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                }
65285b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                clearClientLocked();
65385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mRemoteInstance = null;
65485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mContext.unbindService(mServiceConnection);
65585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                return;
65685b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            }
65785b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            try {
65885b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                mLock.wait();
65985b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            } catch (InterruptedException ie) {
66085b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov                /* ignore */
66185b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            }
662a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
66385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov
664a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
665a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
666a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private void setClientLocked() {
667a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        try {
668a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            mRemoteInstance.setClient(mClient);
669a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        } catch (RemoteException re) {
670a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            Slog.d(LOG_TAG, "Error setting print spooler client", re);
671a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
672a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
673a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
674a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private void clearClientLocked() {
675a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        try {
676a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            mRemoteInstance.setClient(null);
677a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        } catch (RemoteException re) {
678a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            Slog.d(LOG_TAG, "Error clearing print spooler client", re);
679a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
680a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
681a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
682a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
683a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private void throwIfDestroyedLocked() {
684a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        if (mDestroyed) {
685a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            throw new IllegalStateException("Cannot interact with a destroyed instance.");
686a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
687a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
688a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
689a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private void throwIfCalledOnMainThread() {
690a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        if (Thread.currentThread() == mContext.getMainLooper().getThread()) {
691a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            throw new RuntimeException("Cannot invoke on the main thread");
692a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
693a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
694a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
695a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private final class MyServiceConnection implements ServiceConnection {
696a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        @Override
697a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onServiceConnected(ComponentName name, IBinder service) {
698a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            synchronized (mLock) {
699a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                mRemoteInstance = IPrintSpooler.Stub.asInterface(service);
700a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                setClientLocked();
701a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                mLock.notifyAll();
702a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            }
703a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
704a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
705a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        @Override
706a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onServiceDisconnected(ComponentName name) {
707a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            synchronized (mLock) {
708a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                clearClientLocked();
709a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                mRemoteInstance = null;
710a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            }
711a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
712a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
713a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
714a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private static final class GetPrintJobInfosCaller
715a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            extends TimedRemoteCaller<List<PrintJobInfo>> {
716a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        private final IPrintSpoolerCallbacks mCallback;
717a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
718a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public GetPrintJobInfosCaller() {
719a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS);
720a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            mCallback = new BasePrintSpoolerServiceCallbacks() {
721a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                @Override
722a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                public void onGetPrintJobInfosResult(List<PrintJobInfo> printJobs, int sequence) {
723a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    onRemoteMethodResult(printJobs, sequence);
724a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                }
725a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            };
726a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
727a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
728a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public List<PrintJobInfo> getPrintJobInfos(IPrintSpooler target,
729a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                ComponentName componentName, int state, int appId)
730a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                        throws RemoteException, TimeoutException {
731a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            final int sequence = onBeforeRemoteCall();
732a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            target.getPrintJobInfos(mCallback, componentName, state, appId, sequence);
733a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            return getResultTimed(sequence);
734a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
735a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
736a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
737a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private static final class GetPrintJobInfoCaller extends TimedRemoteCaller<PrintJobInfo> {
738a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        private final IPrintSpoolerCallbacks mCallback;
739a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
740a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public GetPrintJobInfoCaller() {
741a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS);
742a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            mCallback = new BasePrintSpoolerServiceCallbacks() {
743a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                @Override
744a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                public void onGetPrintJobInfoResult(PrintJobInfo printJob, int sequence) {
745a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    onRemoteMethodResult(printJob, sequence);
746a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                }
747a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            };
748a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
749a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
7502fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        public PrintJobInfo getPrintJobInfo(IPrintSpooler target, PrintJobId printJobId,
751a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                int appId) throws RemoteException, TimeoutException {
752a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            final int sequence = onBeforeRemoteCall();
753a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            target.getPrintJobInfo(printJobId, mCallback, appId, sequence);
754a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            return getResultTimed(sequence);
755a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
756a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
757a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
758a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private static final class SetPrintJobStateCaller extends TimedRemoteCaller<Boolean> {
759a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        private final IPrintSpoolerCallbacks mCallback;
760a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
761a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public SetPrintJobStateCaller() {
762a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS);
763a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            mCallback = new BasePrintSpoolerServiceCallbacks() {
764a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                @Override
765a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                public void onSetPrintJobStateResult(boolean success, int sequence) {
766a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    onRemoteMethodResult(success, sequence);
767a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                }
768a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            };
769a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
770a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
7712fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        public boolean setPrintJobState(IPrintSpooler target, PrintJobId printJobId,
772269403b032f965ff3847eb982c2f697229dc5a92Svetoslav                int status, String error) throws RemoteException, TimeoutException {
773a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            final int sequence = onBeforeRemoteCall();
7748c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov            target.setPrintJobState(printJobId, status, error, mCallback, sequence);
775a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            return getResultTimed(sequence);
776a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
777a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
778a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
779a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private static final class SetPrintJobTagCaller extends TimedRemoteCaller<Boolean> {
780a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        private final IPrintSpoolerCallbacks mCallback;
781a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
782a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public SetPrintJobTagCaller() {
783a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS);
784a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            mCallback = new BasePrintSpoolerServiceCallbacks() {
785a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                @Override
786a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                public void onSetPrintJobTagResult(boolean success, int sequence) {
787a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    onRemoteMethodResult(success, sequence);
788a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                }
789a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            };
790a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
791a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
7922fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav        public boolean setPrintJobTag(IPrintSpooler target, PrintJobId printJobId,
793a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                String tag) throws RemoteException, TimeoutException {
794a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            final int sequence = onBeforeRemoteCall();
795a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            target.setPrintJobTag(printJobId, tag, mCallback, sequence);
796a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            return getResultTimed(sequence);
797a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
798a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
799a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
800bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    private static final class OnCustomPrinterIconLoadedCaller extends TimedRemoteCaller<Void> {
801bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        private final IPrintSpoolerCallbacks mCallback;
802bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
803bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        public OnCustomPrinterIconLoadedCaller() {
804bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS);
805bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            mCallback = new BasePrintSpoolerServiceCallbacks() {
806bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                @Override
807bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                public void onCustomPrinterIconCached(int sequence) {
808bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                    onRemoteMethodResult(null, sequence);
809bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                }
810bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            };
811bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
812bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
813bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        public Void onCustomPrinterIconLoaded(IPrintSpooler target, PrinterId printerId,
814bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                Icon icon) throws RemoteException, TimeoutException {
815bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            final int sequence = onBeforeRemoteCall();
816bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            target.onCustomPrinterIconLoaded(printerId, icon, mCallback, sequence);
817bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            return getResultTimed(sequence);
818bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
819bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    }
820bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
821bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    private static final class ClearCustomPrinterIconCacheCaller extends TimedRemoteCaller<Void> {
822bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        private final IPrintSpoolerCallbacks mCallback;
823bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
824bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        public ClearCustomPrinterIconCacheCaller() {
825bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS);
826bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            mCallback = new BasePrintSpoolerServiceCallbacks() {
827bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                @Override
828bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                public void customPrinterIconCacheCleared(int sequence) {
829bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                    onRemoteMethodResult(null, sequence);
830bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                }
831bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            };
832bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
833bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
834bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        public Void clearCustomPrinterIconCache(IPrintSpooler target)
835bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                throws RemoteException, TimeoutException {
836bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            final int sequence = onBeforeRemoteCall();
837bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            target.clearCustomPrinterIconCache(mCallback, sequence);
838bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            return getResultTimed(sequence);
839bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
840bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    }
841bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
842bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    private static final class GetCustomPrinterIconCaller extends TimedRemoteCaller<Icon> {
843bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        private final IPrintSpoolerCallbacks mCallback;
844bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
845bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        public GetCustomPrinterIconCaller() {
846bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS);
847bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            mCallback = new BasePrintSpoolerServiceCallbacks() {
848bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                @Override
849bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                public void onGetCustomPrinterIconResult(Icon icon, int sequence) {
850bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                    onRemoteMethodResult(icon, sequence);
851bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                }
852bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            };
853bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
854bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
855bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        public Icon getCustomPrinterIcon(IPrintSpooler target, PrinterId printerId)
856bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann                throws RemoteException, TimeoutException {
857bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            final int sequence = onBeforeRemoteCall();
858bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            target.getCustomPrinterIcon(printerId, mCallback, sequence);
859bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            return getResultTimed(sequence);
860bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
861bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann    }
862bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
863a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private static abstract class BasePrintSpoolerServiceCallbacks
864a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            extends IPrintSpoolerCallbacks.Stub {
865a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        @Override
866a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onGetPrintJobInfosResult(List<PrintJobInfo> printJobIds, int sequence) {
867a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            /* do nothing */
868a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
869a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
870a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        @Override
871a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onGetPrintJobInfoResult(PrintJobInfo printJob, int sequence) {
872a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            /* do nothing */
873a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
874a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
875a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        @Override
876a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onCancelPrintJobResult(boolean canceled, int sequence) {
877a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            /* do nothing */
878a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
879a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
880a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        @Override
881a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onSetPrintJobStateResult(boolean success, int sequece) {
882a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            /* do nothing */
883a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
884a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
885a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        @Override
886a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onSetPrintJobTagResult(boolean success, int sequence) {
887a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            /* do nothing */
888a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
889bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
890bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        @Override
891bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        public void onCustomPrinterIconCached(int sequence) {
892bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            /* do nothing */
893bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
894bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
895bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        @Override
896bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        public void onGetCustomPrinterIconResult(@Nullable Icon icon, int sequence) {
897bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            /* do nothing */
898bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
899bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann
900bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        @Override
901bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        public void customPrinterIconCacheCleared(int sequence) {
902bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann            /* do nothing */
903bb9f686b40743df2642b7d3b7778dbf7284ae665Philip P. Moltmann        }
904a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
905a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
906a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private static final class PrintSpoolerClient extends IPrintSpoolerClient.Stub {
907a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
908a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        private final WeakReference<RemotePrintSpooler> mWeakSpooler;
909a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
910a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public PrintSpoolerClient(RemotePrintSpooler spooler) {
911a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            mWeakSpooler = new WeakReference<RemotePrintSpooler>(spooler);
912a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
913a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
914a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        @Override
915a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onPrintJobQueued(PrintJobInfo printJob) {
916a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            RemotePrintSpooler spooler = mWeakSpooler.get();
917a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            if (spooler != null) {
918a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                final long identity = Binder.clearCallingIdentity();
919a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                try {
920a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    spooler.mCallbacks.onPrintJobQueued(printJob);
921a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                } finally {
922a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    Binder.restoreCallingIdentity(identity);
923a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                }
924a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            }
925a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
926a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
927a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        @Override
928a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onAllPrintJobsForServiceHandled(ComponentName printService) {
929a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            RemotePrintSpooler spooler = mWeakSpooler.get();
930a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            if (spooler != null) {
931a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                final long identity = Binder.clearCallingIdentity();
932a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                try {
933a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    spooler.mCallbacks.onAllPrintJobsForServiceHandled(printService);
934a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                } finally {
935a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    Binder.restoreCallingIdentity(identity);
936a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                }
937a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            }
938a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
939a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
940a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        @Override
941a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        public void onAllPrintJobsHandled() {
942a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            RemotePrintSpooler spooler = mWeakSpooler.get();
943a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            if (spooler != null) {
944a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                final long identity = Binder.clearCallingIdentity();
945a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                try {
946a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    spooler.onAllPrintJobsHandled();
947a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                } finally {
948a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    Binder.restoreCallingIdentity(identity);
949a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                }
950a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            }
951a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        }
952704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov
953704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        @Override
954dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov        public void onPrintJobStateChanged(PrintJobInfo printJob) {
955704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            RemotePrintSpooler spooler = mWeakSpooler.get();
956704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            if (spooler != null) {
957704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                final long identity = Binder.clearCallingIdentity();
958704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                try {
959dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov                    spooler.onPrintJobStateChanged(printJob);
960704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                } finally {
961704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                    Binder.restoreCallingIdentity(identity);
962704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov                }
963704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov            }
964704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov        }
965a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
966a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov}
967