FileDocCategorySizeDatePackage
RemotePrintSpooler.javaAPI DocAndroid 5.1 API22109Thu Mar 12 22:22:42 GMT 2015com.android.server.print

RemotePrintSpooler

public final class RemotePrintSpooler extends Object
This represents the remote print spooler as a local object to the PrintManagerService. It is responsible to connecting to the remote spooler if needed, to make the timed remote calls, to handle remote exceptions, and to bind/unbind to the remote instance as needed.

Fields Summary
private static final String
LOG_TAG
private static final boolean
DEBUG
private static final long
BIND_SPOOLER_SERVICE_TIMEOUT
private final Object
mLock
private final GetPrintJobInfosCaller
mGetPrintJobInfosCaller
private final GetPrintJobInfoCaller
mGetPrintJobInfoCaller
private final SetPrintJobStateCaller
mSetPrintJobStatusCaller
private final SetPrintJobTagCaller
mSetPrintJobTagCaller
private final android.content.ServiceConnection
mServiceConnection
private final android.content.Context
mContext
private final android.os.UserHandle
mUserHandle
private final PrintSpoolerClient
mClient
private final android.content.Intent
mIntent
private final PrintSpoolerCallbacks
mCallbacks
private android.print.IPrintSpooler
mRemoteInstance
private boolean
mDestroyed
private boolean
mCanUnbind
Constructors Summary
public RemotePrintSpooler(android.content.Context context, int userId, PrintSpoolerCallbacks callbacks)


        
           
           
           
    

        
              
        mContext = context;
        mUserHandle = new UserHandle(userId);
        mCallbacks = callbacks;
        mClient = new PrintSpoolerClient(this);
        mIntent = new Intent();
        mIntent.setComponent(new ComponentName("com.android.printspooler",
                "com.android.printspooler.model.PrintSpoolerService"));
    
Methods Summary
private voidbindLocked()

        if (mRemoteInstance != null) {
            return;
        }
        if (DEBUG) {
            Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] bindLocked()");
        }

        mContext.bindServiceAsUser(mIntent, mServiceConnection,
                Context.BIND_AUTO_CREATE, mUserHandle);

        final long startMillis = SystemClock.uptimeMillis();
        while (true) {
            if (mRemoteInstance != null) {
                break;
            }
            final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
            final long remainingMillis = BIND_SPOOLER_SERVICE_TIMEOUT - elapsedMillis;
            if (remainingMillis <= 0) {
                throw new TimeoutException("Cannot get spooler!");
            }
            try {
                mLock.wait(remainingMillis);
            } catch (InterruptedException ie) {
                /* ignore */
            }
        }

        mCanUnbind = true;
        mLock.notifyAll();
    
private voidclearClientLocked()

        try {
            mRemoteInstance.setClient(null);
        } catch (RemoteException re) {
            Slog.d(LOG_TAG, "Error clearing print spooler client", re);
        }

    
public final voidcreatePrintJob(android.print.PrintJobInfo printJob)

        throwIfCalledOnMainThread();
        synchronized (mLock) {
            throwIfDestroyedLocked();
            mCanUnbind = false;
        }
        try {
            getRemoteInstanceLazy().createPrintJob(printJob);
        } catch (RemoteException re) {
            Slog.e(LOG_TAG, "Error creating print job.", re);
        } catch (TimeoutException te) {
            Slog.e(LOG_TAG, "Error creating print job.", te);
        } finally {
            if (DEBUG) {
                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] createPrintJob()");
            }
            synchronized (mLock) {
                mCanUnbind = true;
                mLock.notifyAll();
            }
        }
    
public final voiddestroy()

        throwIfCalledOnMainThread();
        if (DEBUG) {
            Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] destroy()");
        }
        synchronized (mLock) {
            throwIfDestroyedLocked();
            unbindLocked();
            mDestroyed = true;
            mCanUnbind = false;
        }
    
public voiddump(java.io.FileDescriptor fd, java.io.PrintWriter pw, java.lang.String prefix)

        synchronized (mLock) {
            pw.append(prefix).append("destroyed=")
                    .append(String.valueOf(mDestroyed)).println();
            pw.append(prefix).append("bound=")
                    .append((mRemoteInstance != null) ? "true" : "false").println();

            pw.flush();

            try {
                getRemoteInstanceLazy().asBinder().dump(fd, new String[]{prefix});
            } catch (TimeoutException te) {
                /* ignore */
            } catch (RemoteException re) {
                /* ignore */
            }
        }
    
public final android.print.PrintJobInfogetPrintJobInfo(android.print.PrintJobId printJobId, int appId)

        throwIfCalledOnMainThread();
        synchronized (mLock) {
            throwIfDestroyedLocked();
            mCanUnbind = false;
        }
        try {
            return mGetPrintJobInfoCaller.getPrintJobInfo(getRemoteInstanceLazy(),
                    printJobId, appId);
        } catch (RemoteException re) {
            Slog.e(LOG_TAG, "Error getting print job info.", re);
        } catch (TimeoutException te) {
            Slog.e(LOG_TAG, "Error getting print job info.", te);
        } finally {
            if (DEBUG) {
                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] getPrintJobInfo()");
            }
            synchronized (mLock) {
                mCanUnbind = true;
                mLock.notifyAll();
            }
        }
        return null;
    
public final java.util.ListgetPrintJobInfos(android.content.ComponentName componentName, int state, int appId)

        throwIfCalledOnMainThread();
        synchronized (mLock) {
            throwIfDestroyedLocked();
            mCanUnbind = false;
        }
        try {
            return mGetPrintJobInfosCaller.getPrintJobInfos(getRemoteInstanceLazy(),
                    componentName, state, appId);
        } catch (RemoteException re) {
            Slog.e(LOG_TAG, "Error getting print jobs.", re);
        } catch (TimeoutException te) {
            Slog.e(LOG_TAG, "Error getting print jobs.", te);
        } finally {
            if (DEBUG) {
                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] getPrintJobInfos()");
            }
            synchronized (mLock) {
                mCanUnbind = true;
                mLock.notifyAll();
            }
        }
        return null;
    
private android.print.IPrintSpoolergetRemoteInstanceLazy()

        synchronized (mLock) {
            if (mRemoteInstance != null) {
                return mRemoteInstance;
            }
            bindLocked();
            return mRemoteInstance;
        }
    
private voidonAllPrintJobsHandled()

        synchronized (mLock) {
            throwIfDestroyedLocked();
            unbindLocked();
        }
    
private voidonPrintJobStateChanged(android.print.PrintJobInfo printJob)

        mCallbacks.onPrintJobStateChanged(printJob);
    
public final voidremoveObsoletePrintJobs()

        throwIfCalledOnMainThread();
        synchronized (mLock) {
            throwIfDestroyedLocked();
            mCanUnbind = false;
        }
        try {
            getRemoteInstanceLazy().removeObsoletePrintJobs();
        } catch (RemoteException re) {
            Slog.e(LOG_TAG, "Error removing obsolete print jobs .", re);
        } catch (TimeoutException te) {
            Slog.e(LOG_TAG, "Error removing obsolete print jobs .", te);
        } finally {
            if (DEBUG) {
                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
                        + "] removeObsoletePrintJobs()");
            }
            synchronized (mLock) {
                mCanUnbind = true;
                mLock.notifyAll();
            }
        }
    
private voidsetClientLocked()

        try {
            mRemoteInstance.setClient(mClient);
        } catch (RemoteException re) {
            Slog.d(LOG_TAG, "Error setting print spooler client", re);
        }
    
public final voidsetPrintJobCancelling(android.print.PrintJobId printJobId, boolean cancelling)

        throwIfCalledOnMainThread();
        synchronized (mLock) {
            throwIfDestroyedLocked();
            mCanUnbind = false;
        }
        try {
            getRemoteInstanceLazy().setPrintJobCancelling(printJobId,
                    cancelling);
        } catch (RemoteException re) {
            Slog.e(LOG_TAG, "Error setting print job cancelling.", re);
        } catch (TimeoutException te) {
            Slog.e(LOG_TAG, "Error setting print job cancelling.", te);
        } finally {
            if (DEBUG) {
                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
                        + "] setPrintJobCancelling()");
            }
            synchronized (mLock) {
                mCanUnbind = true;
                mLock.notifyAll();
            }
        }
    
public final booleansetPrintJobState(android.print.PrintJobId printJobId, int state, java.lang.String error)

        throwIfCalledOnMainThread();
        synchronized (mLock) {
            throwIfDestroyedLocked();
            mCanUnbind = false;
        }
        try {
            return mSetPrintJobStatusCaller.setPrintJobState(getRemoteInstanceLazy(),
                    printJobId, state, error);
        } catch (RemoteException re) {
            Slog.e(LOG_TAG, "Error setting print job state.", re);
        } catch (TimeoutException te) {
            Slog.e(LOG_TAG, "Error setting print job state.", te);
        } finally {
            if (DEBUG) {
                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setPrintJobState()");
            }
            synchronized (mLock) {
                mCanUnbind = true;
                mLock.notifyAll();
            }
        }
        return false;
    
public final booleansetPrintJobTag(android.print.PrintJobId printJobId, java.lang.String tag)

        throwIfCalledOnMainThread();
        synchronized (mLock) {
            throwIfDestroyedLocked();
            mCanUnbind = false;
        }
        try {
            return mSetPrintJobTagCaller.setPrintJobTag(getRemoteInstanceLazy(),
                    printJobId, tag);
        } catch (RemoteException re) {
            Slog.e(LOG_TAG, "Error setting print job tag.", re);
        } catch (TimeoutException te) {
            Slog.e(LOG_TAG, "Error setting print job tag.", te);
        } finally {
            if (DEBUG) {
                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setPrintJobTag()");
            }
            synchronized (mLock) {
                mCanUnbind = true;
                mLock.notifyAll();
            }
        }
        return false;
    
private voidthrowIfCalledOnMainThread()

        if (Thread.currentThread() == mContext.getMainLooper().getThread()) {
            throw new RuntimeException("Cannot invoke on the main thread");
        }
    
private voidthrowIfDestroyedLocked()

        if (mDestroyed) {
            throw new IllegalStateException("Cannot interact with a destroyed instance.");
        }
    
private voidunbindLocked()

        if (mRemoteInstance == null) {
            return;
        }
        while (true) {
            if (mCanUnbind) {
                if (DEBUG) {
                    Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] unbindLocked()");
                }
                clearClientLocked();
                mRemoteInstance = null;
                mContext.unbindService(mServiceConnection);
                return;
            }
            try {
                mLock.wait();
            } catch (InterruptedException ie) {
                /* ignore */
            }
        }

    
public final voidwritePrintJobData(android.os.ParcelFileDescriptor fd, android.print.PrintJobId printJobId)

        throwIfCalledOnMainThread();
        synchronized (mLock) {
            throwIfDestroyedLocked();
            mCanUnbind = false;
        }
        try {
            getRemoteInstanceLazy().writePrintJobData(fd, printJobId);
        } catch (RemoteException re) {
            Slog.e(LOG_TAG, "Error writing print job data.", re);
        } catch (TimeoutException te) {
            Slog.e(LOG_TAG, "Error writing print job data.", te);
        } finally {
            if (DEBUG) {
                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] writePrintJobData()");
            }
            // We passed the file descriptor across and now the other
            // side is responsible to close it, so close the local copy.
            IoUtils.closeQuietly(fd);
            synchronized (mLock) {
                mCanUnbind = true;
                mLock.notifyAll();
            }
        }