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 19a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.content.ComponentName; 20a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.content.Context; 21a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.content.Intent; 22a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.content.ServiceConnection; 23a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.os.Binder; 24a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.os.IBinder; 25a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.os.ParcelFileDescriptor; 26a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.os.RemoteException; 27a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.os.SystemClock; 28a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.os.UserHandle; 29a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.IPrintSpooler; 30a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.IPrintSpoolerCallbacks; 31a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.IPrintSpoolerClient; 322fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslavimport android.print.PrintJobId; 33a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.print.PrintJobInfo; 34a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.util.Slog; 35a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport android.util.TimedRemoteCaller; 36a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 37b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganovimport java.io.FileDescriptor; 38b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganovimport java.io.PrintWriter; 39a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport java.lang.ref.WeakReference; 40a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport java.util.List; 41a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovimport java.util.concurrent.TimeoutException; 42a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 432fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslavimport libcore.io.IoUtils; 442fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav 45a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov/** 46a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * This represents the remote print spooler as a local object to the 47a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * PrintManagerSerivce. It is responsible to connecting to the remote 48a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * spooler if needed, to make the timed remote calls, to handle 49a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * remote exceptions, and to bind/unbind to the remote instance as 50a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * needed. 51a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov */ 52a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovfinal class RemotePrintSpooler { 53a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 54a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private static final String LOG_TAG = "RemotePrintSpooler"; 55a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 56c6066799ad130140159230d14451b429eb828755Svetoslav private static final boolean DEBUG = false; 57a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 58a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private static final long BIND_SPOOLER_SERVICE_TIMEOUT = 10000; 59a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 60a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final Object mLock = new Object(); 61a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 62a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final GetPrintJobInfosCaller mGetPrintJobInfosCaller = new GetPrintJobInfosCaller(); 63a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 64a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final GetPrintJobInfoCaller mGetPrintJobInfoCaller = new GetPrintJobInfoCaller(); 65a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 66a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final SetPrintJobStateCaller mSetPrintJobStatusCaller = new SetPrintJobStateCaller(); 67a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 68a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final SetPrintJobTagCaller mSetPrintJobTagCaller = new SetPrintJobTagCaller(); 69a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 70a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final ServiceConnection mServiceConnection = new MyServiceConnection(); 71a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 72a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final Context mContext; 73a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 74a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final UserHandle mUserHandle; 75a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 76a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final PrintSpoolerClient mClient; 77a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 78a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final Intent mIntent; 79a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 80a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final PrintSpoolerCallbacks mCallbacks; 81a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 82a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private IPrintSpooler mRemoteInstance; 83a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 84a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private boolean mDestroyed; 85a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 8685b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov private boolean mCanUnbind; 8785b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov 88a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public static interface PrintSpoolerCallbacks { 89a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onPrintJobQueued(PrintJobInfo printJob); 90a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onAllPrintJobsForServiceHandled(ComponentName printService); 91dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov public void onPrintJobStateChanged(PrintJobInfo printJob); 92a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 93a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 94a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public RemotePrintSpooler(Context context, int userId, 95a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov PrintSpoolerCallbacks callbacks) { 96a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mContext = context; 97a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mUserHandle = new UserHandle(userId); 98a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mCallbacks = callbacks; 99a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mClient = new PrintSpoolerClient(this); 100a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mIntent = new Intent(); 101a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mIntent.setComponent(new ComponentName("com.android.printspooler", 102a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov "com.android.printspooler.PrintSpoolerService")); 103a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 104a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 105a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public final List<PrintJobInfo> getPrintJobInfos(ComponentName componentName, int state, 106a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov int appId) { 107a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov throwIfCalledOnMainThread(); 108a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov synchronized (mLock) { 109a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov throwIfDestroyedLocked(); 11085b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mCanUnbind = false; 111a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 112a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov try { 113a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return mGetPrintJobInfosCaller.getPrintJobInfos(getRemoteInstanceLazy(), 114a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov componentName, state, appId); 115a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } catch (RemoteException re) { 116a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Slog.e(LOG_TAG, "Error getting print jobs.", re); 117a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } catch (TimeoutException te) { 118a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Slog.e(LOG_TAG, "Error getting print jobs.", te); 11985b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov } finally { 120835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov if (DEBUG) { 121835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] getPrintJobInfos()"); 122835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 12385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov synchronized (mLock) { 12485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mCanUnbind = true; 12585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mLock.notifyAll(); 12685b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov } 127a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 128a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return null; 129a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 130a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 1317bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav public final void createPrintJob(PrintJobInfo printJob) { 132a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov throwIfCalledOnMainThread(); 133a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov synchronized (mLock) { 134a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov throwIfDestroyedLocked(); 13585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mCanUnbind = false; 136a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 137a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov try { 1387bfbbcb04bf4ba8f3069b2df136f708c9849bacfSvetoslav getRemoteInstanceLazy().createPrintJob(printJob); 139a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } catch (RemoteException re) { 140a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Slog.e(LOG_TAG, "Error creating print job.", re); 141a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } catch (TimeoutException te) { 142a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Slog.e(LOG_TAG, "Error creating print job.", te); 14385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov } finally { 144835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov if (DEBUG) { 145835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] createPrintJob()"); 146835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 14785b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov synchronized (mLock) { 14885b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mCanUnbind = true; 14985b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mLock.notifyAll(); 15085b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov } 151a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 152a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 153a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 1542fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public final void writePrintJobData(ParcelFileDescriptor fd, PrintJobId printJobId) { 155a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov throwIfCalledOnMainThread(); 156a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov synchronized (mLock) { 157a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov throwIfDestroyedLocked(); 15885b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mCanUnbind = false; 159a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 160a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov try { 161a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov getRemoteInstanceLazy().writePrintJobData(fd, printJobId); 162a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } catch (RemoteException re) { 163a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Slog.e(LOG_TAG, "Error writing print job data.", re); 164a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } catch (TimeoutException te) { 165a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Slog.e(LOG_TAG, "Error writing print job data.", te); 166a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } finally { 167835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov if (DEBUG) { 168835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] writePrintJobData()"); 169835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 170a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov // We passed the file descriptor across and now the other 171a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov // side is responsible to close it, so close the local copy. 172a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov IoUtils.closeQuietly(fd); 17385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov synchronized (mLock) { 17485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mCanUnbind = true; 17585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mLock.notifyAll(); 17685b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov } 177a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 178a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 179a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 1802fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public final PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId) { 181a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov throwIfCalledOnMainThread(); 182a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov synchronized (mLock) { 183a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov throwIfDestroyedLocked(); 18485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mCanUnbind = false; 185a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 186a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov try { 187a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return mGetPrintJobInfoCaller.getPrintJobInfo(getRemoteInstanceLazy(), 188a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov printJobId, appId); 189a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } catch (RemoteException re) { 190a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Slog.e(LOG_TAG, "Error getting print job info.", re); 191a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } catch (TimeoutException te) { 192a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Slog.e(LOG_TAG, "Error getting print job info.", te); 19385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov } finally { 194835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov if (DEBUG) { 195835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] getPrintJobInfo()"); 196835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 19785b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov synchronized (mLock) { 19885b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mCanUnbind = true; 19985b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mLock.notifyAll(); 20085b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov } 201a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 202a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return null; 203a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 204a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 2052fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public final boolean setPrintJobState(PrintJobId printJobId, int state, String error) { 206a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov throwIfCalledOnMainThread(); 207a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov synchronized (mLock) { 208a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov throwIfDestroyedLocked(); 20985b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mCanUnbind = false; 210a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 211a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov try { 212a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return mSetPrintJobStatusCaller.setPrintJobState(getRemoteInstanceLazy(), 2138c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov printJobId, state, error); 214a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } catch (RemoteException re) { 215a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Slog.e(LOG_TAG, "Error setting print job state.", re); 216a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } catch (TimeoutException te) { 217a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Slog.e(LOG_TAG, "Error setting print job state.", te); 21885b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov } finally { 219835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov if (DEBUG) { 220835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setPrintJobState()"); 221835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 22285b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov synchronized (mLock) { 22385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mCanUnbind = true; 22485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mLock.notifyAll(); 22585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov } 226a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 227a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return false; 228a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 229a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 2302fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public final boolean setPrintJobTag(PrintJobId printJobId, String tag) { 231a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov throwIfCalledOnMainThread(); 232a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov synchronized (mLock) { 233a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov throwIfDestroyedLocked(); 23485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mCanUnbind = false; 235a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 236a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov try { 237a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return mSetPrintJobTagCaller.setPrintJobTag(getRemoteInstanceLazy(), 238a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov printJobId, tag); 239a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } catch (RemoteException re) { 240a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Slog.e(LOG_TAG, "Error setting print job tag.", re); 241a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } catch (TimeoutException te) { 242a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Slog.e(LOG_TAG, "Error setting print job tag.", te); 24385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov } finally { 244835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov if (DEBUG) { 245835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setPrintJobTag()"); 246835835ee6f913408ac91678d6056896a2c5b25e3Svetoslav Ganov } 24785b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov synchronized (mLock) { 24885b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mCanUnbind = true; 24985b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mLock.notifyAll(); 25085b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov } 251a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 252a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return false; 253a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 254a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 255a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov public final void setPrintJobCancelling(PrintJobId printJobId, boolean cancelling) { 256a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov throwIfCalledOnMainThread(); 257a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov synchronized (mLock) { 258a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov throwIfDestroyedLocked(); 259a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov mCanUnbind = false; 260a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } 261a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov try { 262a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov getRemoteInstanceLazy().setPrintJobCancelling(printJobId, 263a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov cancelling); 264a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } catch (RemoteException re) { 265a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov Slog.e(LOG_TAG, "Error setting print job cancelling.", re); 266a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } catch (TimeoutException te) { 267a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov Slog.e(LOG_TAG, "Error setting print job cancelling.", te); 268a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } finally { 269a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov if (DEBUG) { 270a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() 271a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov + "] setPrintJobCancelling()"); 272a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } 273a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov synchronized (mLock) { 274a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov mCanUnbind = true; 275a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov mLock.notifyAll(); 276a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } 277a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } 278a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov } 279a18661d5922e5ae24ccce8e815aeba437a2fba82Svetoslav Ganov 2802fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public final void removeObsoletePrintJobs() { 2812fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav throwIfCalledOnMainThread(); 2822fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav synchronized (mLock) { 2832fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav throwIfDestroyedLocked(); 2842fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav mCanUnbind = false; 2852fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 2862fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav try { 2872fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav getRemoteInstanceLazy().removeObsoletePrintJobs(); 2882fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } catch (RemoteException re) { 2892fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav Slog.e(LOG_TAG, "Error removing obsolete print jobs .", re); 2902fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } catch (TimeoutException te) { 2912fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav Slog.e(LOG_TAG, "Error removing obsolete print jobs .", te); 2922fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } finally { 2932fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav if (DEBUG) { 2942fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() 2952fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav + "] removeObsoletePrintJobs()"); 2962fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 2972fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav synchronized (mLock) { 2982fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav mCanUnbind = true; 2992fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav mLock.notifyAll(); 3002fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 3012fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 3022fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 3032fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav 304a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public final void destroy() { 305a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov throwIfCalledOnMainThread(); 306a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (DEBUG) { 307a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] destroy()"); 308a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 309a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov synchronized (mLock) { 310a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov throwIfDestroyedLocked(); 311a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov unbindLocked(); 312a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mDestroyed = true; 31385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mCanUnbind = false; 314a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 315a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 316a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 317b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov public void dump(FileDescriptor fd, PrintWriter pw, String prefix) { 318b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov synchronized (mLock) { 319b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov pw.append(prefix).append("destroyed=") 320b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov .append(String.valueOf(mDestroyed)).println(); 321b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov pw.append(prefix).append("bound=") 322b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov .append((mRemoteInstance != null) ? "true" : "false").println(); 323dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 324dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov pw.flush(); 325dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov 326dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov try { 327dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov getRemoteInstanceLazy().asBinder().dump(fd, new String[]{prefix}); 328dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } catch (TimeoutException te) { 329dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov /* ignore */ 330dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov } catch (RemoteException re) { 331dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov /* ignore */ 332b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov } 333b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov } 334b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov } 335b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov 336a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private void onAllPrintJobsHandled() { 337a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov synchronized (mLock) { 338a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov throwIfDestroyedLocked(); 339a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov unbindLocked(); 340a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 341a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 342a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 343dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov private void onPrintJobStateChanged(PrintJobInfo printJob) { 344dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov mCallbacks.onPrintJobStateChanged(printJob); 345704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 346704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 347a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private IPrintSpooler getRemoteInstanceLazy() throws TimeoutException { 348a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov synchronized (mLock) { 349a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (mRemoteInstance != null) { 350a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return mRemoteInstance; 351a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 352a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov bindLocked(); 353a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return mRemoteInstance; 354a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 355a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 356a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 357a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private void bindLocked() throws TimeoutException { 3582fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav if (mRemoteInstance != null) { 3592fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav return; 3602fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 361a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (DEBUG) { 362a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] bindLocked()"); 363a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 364a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 365a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mContext.bindServiceAsUser(mIntent, mServiceConnection, 366597945fd3a6b52ac70bb9afc5ec8c59039fffd77Svetoslav Context.BIND_AUTO_CREATE, mUserHandle); 367a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 368a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final long startMillis = SystemClock.uptimeMillis(); 369a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov while (true) { 370a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (mRemoteInstance != null) { 371a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov break; 372a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 373a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final long elapsedMillis = SystemClock.uptimeMillis() - startMillis; 374a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final long remainingMillis = BIND_SPOOLER_SERVICE_TIMEOUT - elapsedMillis; 375a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (remainingMillis <= 0) { 376a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov throw new TimeoutException("Cannot get spooler!"); 377a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 378a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov try { 379a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mLock.wait(remainingMillis); 380a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } catch (InterruptedException ie) { 381a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov /* ignore */ 382a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 383a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 38485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov 38585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mCanUnbind = true; 38685b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mLock.notifyAll(); 387a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 388a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 389a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private void unbindLocked() { 3902fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav if (mRemoteInstance == null) { 3912fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav return; 3922fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav } 39385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov while (true) { 39485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov if (mCanUnbind) { 39585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov if (DEBUG) { 39685b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] unbindLocked()"); 39785b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov } 39885b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov clearClientLocked(); 39985b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mRemoteInstance = null; 40085b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mContext.unbindService(mServiceConnection); 40185b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov return; 40285b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov } 40385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov try { 40485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mLock.wait(); 40585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov } catch (InterruptedException ie) { 40685b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov /* ignore */ 40785b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov } 408a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 40985b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov 410a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 411a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 412a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private void setClientLocked() { 413a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov try { 414a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mRemoteInstance.setClient(mClient); 415a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } catch (RemoteException re) { 416a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Slog.d(LOG_TAG, "Error setting print spooler client", re); 417a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 418a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 419a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 420a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private void clearClientLocked() { 421a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov try { 422a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mRemoteInstance.setClient(null); 423a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } catch (RemoteException re) { 424a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Slog.d(LOG_TAG, "Error clearing print spooler client", re); 425a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 426a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 427a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 428a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 429a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private void throwIfDestroyedLocked() { 430a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (mDestroyed) { 431a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov throw new IllegalStateException("Cannot interact with a destroyed instance."); 432a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 433a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 434a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 435a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private void throwIfCalledOnMainThread() { 436a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (Thread.currentThread() == mContext.getMainLooper().getThread()) { 437a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov throw new RuntimeException("Cannot invoke on the main thread"); 438a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 439a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 440a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 441a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final class MyServiceConnection implements ServiceConnection { 442a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov @Override 443a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onServiceConnected(ComponentName name, IBinder service) { 444a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov synchronized (mLock) { 445a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mRemoteInstance = IPrintSpooler.Stub.asInterface(service); 446a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov setClientLocked(); 447a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mLock.notifyAll(); 448a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 449a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 450a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 451a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov @Override 452a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onServiceDisconnected(ComponentName name) { 453a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov synchronized (mLock) { 454a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov clearClientLocked(); 455a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mRemoteInstance = null; 456a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 457a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 458a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 459a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 460a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private static final class GetPrintJobInfosCaller 461a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov extends TimedRemoteCaller<List<PrintJobInfo>> { 462a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final IPrintSpoolerCallbacks mCallback; 463a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 464a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public GetPrintJobInfosCaller() { 465a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS); 466a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mCallback = new BasePrintSpoolerServiceCallbacks() { 467a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov @Override 468a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onGetPrintJobInfosResult(List<PrintJobInfo> printJobs, int sequence) { 469a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov onRemoteMethodResult(printJobs, sequence); 470a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 471a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov }; 472a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 473a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 474a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public List<PrintJobInfo> getPrintJobInfos(IPrintSpooler target, 475a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov ComponentName componentName, int state, int appId) 476a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov throws RemoteException, TimeoutException { 477a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final int sequence = onBeforeRemoteCall(); 478a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov target.getPrintJobInfos(mCallback, componentName, state, appId, sequence); 479a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return getResultTimed(sequence); 480a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 481a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 482a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 483a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private static final class GetPrintJobInfoCaller extends TimedRemoteCaller<PrintJobInfo> { 484a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final IPrintSpoolerCallbacks mCallback; 485a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 486a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public GetPrintJobInfoCaller() { 487a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS); 488a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mCallback = new BasePrintSpoolerServiceCallbacks() { 489a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov @Override 490a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onGetPrintJobInfoResult(PrintJobInfo printJob, int sequence) { 491a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov onRemoteMethodResult(printJob, sequence); 492a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 493a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov }; 494a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 495a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 4962fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public PrintJobInfo getPrintJobInfo(IPrintSpooler target, PrintJobId printJobId, 497a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov int appId) throws RemoteException, TimeoutException { 498a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final int sequence = onBeforeRemoteCall(); 499a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov target.getPrintJobInfo(printJobId, mCallback, appId, sequence); 500a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return getResultTimed(sequence); 501a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 502a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 503a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 504a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private static final class SetPrintJobStateCaller extends TimedRemoteCaller<Boolean> { 505a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final IPrintSpoolerCallbacks mCallback; 506a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 507a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public SetPrintJobStateCaller() { 508a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS); 509a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mCallback = new BasePrintSpoolerServiceCallbacks() { 510a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov @Override 511a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onSetPrintJobStateResult(boolean success, int sequence) { 512a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov onRemoteMethodResult(success, sequence); 513a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 514a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov }; 515a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 516a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 5172fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public boolean setPrintJobState(IPrintSpooler target, PrintJobId printJobId, 518269403b032f965ff3847eb982c2f697229dc5a92Svetoslav int status, String error) throws RemoteException, TimeoutException { 519a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final int sequence = onBeforeRemoteCall(); 5208c43376ea83a67414bd6823a472b76d41160239eSvetoslav Ganov target.setPrintJobState(printJobId, status, error, mCallback, sequence); 521a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return getResultTimed(sequence); 522a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 523a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 524a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 525a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private static final class SetPrintJobTagCaller extends TimedRemoteCaller<Boolean> { 526a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final IPrintSpoolerCallbacks mCallback; 527a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 528a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public SetPrintJobTagCaller() { 529a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS); 530a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mCallback = new BasePrintSpoolerServiceCallbacks() { 531a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov @Override 532a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onSetPrintJobTagResult(boolean success, int sequence) { 533a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov onRemoteMethodResult(success, sequence); 534a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 535a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov }; 536a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 537a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 5382fbd2a7f070f246ddafd9de94efa9a98861e9136Svetoslav public boolean setPrintJobTag(IPrintSpooler target, PrintJobId printJobId, 539a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov String tag) throws RemoteException, TimeoutException { 540a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final int sequence = onBeforeRemoteCall(); 541a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov target.setPrintJobTag(printJobId, tag, mCallback, sequence); 542a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return getResultTimed(sequence); 543a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 544a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 545a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 546a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private static abstract class BasePrintSpoolerServiceCallbacks 547a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov extends IPrintSpoolerCallbacks.Stub { 548a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov @Override 549a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onGetPrintJobInfosResult(List<PrintJobInfo> printJobIds, int sequence) { 550a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov /* do nothing */ 551a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 552a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 553a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov @Override 554a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onGetPrintJobInfoResult(PrintJobInfo printJob, int sequence) { 555a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov /* do nothing */ 556a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 557a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 558a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov @Override 559a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onCancelPrintJobResult(boolean canceled, int sequence) { 560a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov /* do nothing */ 561a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 562a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 563a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov @Override 564a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onSetPrintJobStateResult(boolean success, int sequece) { 565a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov /* do nothing */ 566a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 567a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 568a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov @Override 569a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onSetPrintJobTagResult(boolean success, int sequence) { 570a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov /* do nothing */ 571a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 572a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 573a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 574a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private static final class PrintSpoolerClient extends IPrintSpoolerClient.Stub { 575a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 576a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final WeakReference<RemotePrintSpooler> mWeakSpooler; 577a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 578a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public PrintSpoolerClient(RemotePrintSpooler spooler) { 579a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov mWeakSpooler = new WeakReference<RemotePrintSpooler>(spooler); 580a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 581a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 582a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov @Override 583a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onPrintJobQueued(PrintJobInfo printJob) { 584a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov RemotePrintSpooler spooler = mWeakSpooler.get(); 585a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (spooler != null) { 586a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final long identity = Binder.clearCallingIdentity(); 587a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov try { 588a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov spooler.mCallbacks.onPrintJobQueued(printJob); 589a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } finally { 590a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Binder.restoreCallingIdentity(identity); 591a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 592a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 593a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 594a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 595a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov @Override 596a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onAllPrintJobsForServiceHandled(ComponentName printService) { 597a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov RemotePrintSpooler spooler = mWeakSpooler.get(); 598a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (spooler != null) { 599a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final long identity = Binder.clearCallingIdentity(); 600a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov try { 601a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov spooler.mCallbacks.onAllPrintJobsForServiceHandled(printService); 602a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } finally { 603a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Binder.restoreCallingIdentity(identity); 604a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 605a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 606a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 607a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 608a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov @Override 609a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onAllPrintJobsHandled() { 610a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov RemotePrintSpooler spooler = mWeakSpooler.get(); 611a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (spooler != null) { 612a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final long identity = Binder.clearCallingIdentity(); 613a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov try { 614a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov spooler.onAllPrintJobsHandled(); 615a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } finally { 616a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Binder.restoreCallingIdentity(identity); 617a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 618a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 619a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 620704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov 621704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov @Override 622dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov public void onPrintJobStateChanged(PrintJobInfo printJob) { 623704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov RemotePrintSpooler spooler = mWeakSpooler.get(); 624704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov if (spooler != null) { 625704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov final long identity = Binder.clearCallingIdentity(); 626704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov try { 627dd68da2741fa63070d5ad206020dcccb9f429a5aSvetoslav Ganov spooler.onPrintJobStateChanged(printJob); 628704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } finally { 629704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov Binder.restoreCallingIdentity(identity); 630704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 631704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 632704697b6197262678e930daa831a1916ddee4dcfSvetoslav Ganov } 633a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 634a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov} 635