diff options
Diffstat (limited to 'packages/PrintSpooler/src')
4 files changed, 337 insertions, 371 deletions
diff --git a/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java b/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java index e4de4b8..14a96c9 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java +++ b/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java @@ -22,7 +22,10 @@ import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.os.AsyncTask; import android.os.Build; +import android.os.PowerManager; +import android.os.PowerManager.WakeLock; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; @@ -43,6 +46,8 @@ public class NotificationController { private static final String INTENT_ACTION_CANCEL_PRINTJOB = "INTENT_ACTION_CANCEL_PRINTJOB"; private static final String INTENT_ACTION_RESTART_PRINTJOB = "INTENT_ACTION_RESTART_PRINTJOB"; private static final String INTENT_EXTRA_PRINTJOB_ID = "INTENT_EXTRA_PRINTJOB_ID"; + private static final String INTENT_EXTRA_PRINTJOB_LABEL = "INTENT_EXTRA_PRINTJOB_LABEL"; + private static final String INTENT_EXTRA_PRINTER_NAME = "INTENT_EXTRA_PRINTER_NAME"; private final Context mContext; private final NotificationManager mNotificationManager; @@ -53,11 +58,10 @@ public class NotificationController { mContext.getSystemService(Context.NOTIFICATION_SERVICE); } - public void onPrintJobStateChanged(PrintJobInfo printJob, int oldState) { + public void onPrintJobStateChanged(PrintJobInfo printJob) { if (DEBUG) { Log.i(LOG_TAG, "onPrintJobStateChanged() printJobId: " + printJob.getId() - + " oldState: " + PrintJobInfo.stateToString(oldState) - + " newState:" + PrintJobInfo.stateToString(printJob.getState())); + + " state:" + PrintJobInfo.stateToString(printJob.getState())); } switch (printJob.getState()) { case PrintJobInfo.STATE_QUEUED: { @@ -87,10 +91,10 @@ public class NotificationController { printJob.getLabel())) // TODO: Use appropriate icon when assets are ready .addAction(android.R.drawable.ic_secure, mContext.getString(R.string.cancel), - createCancelIntent(printJob.getId())) + createCancelIntent(printJob)) .setContentText(printJob.getPrinterId().getPrinterName()) - .setOngoing(true) .setWhen(System.currentTimeMillis()) + .setOngoing(true) .setShowWhen(true); mNotificationManager.notify(printJob.getId(), builder.build()); } @@ -103,10 +107,10 @@ public class NotificationController { printJob.getLabel())) // TODO: Use appropriate icon when assets are ready .addAction(android.R.drawable.ic_secure, mContext.getString(R.string.cancel), - createCancelIntent(printJob.getId())) + createCancelIntent(printJob)) .setContentText(printJob.getPrinterId().getPrinterName()) - .setOngoing(true) .setWhen(System.currentTimeMillis()) + .setOngoing(true) .setShowWhen(true); mNotificationManager.notify(printJob.getId(), builder.build()); } @@ -119,13 +123,13 @@ public class NotificationController { printJob.getLabel())) // TODO: Use appropriate icon when assets are ready .addAction(android.R.drawable.ic_secure, mContext.getString(R.string.cancel), - createCancelIntent(printJob.getId())) + createCancelIntent(printJob)) // TODO: Use appropriate icon when assets are ready .addAction(android.R.drawable.ic_secure, mContext.getString(R.string.restart), createRestartIntent(printJob.getId())) .setContentText(printJob.getFailureReason()) - .setOngoing(true) .setWhen(System.currentTimeMillis()) + .setOngoing(true) .setShowWhen(true); mNotificationManager.notify(printJob.getId(), builder.build()); } @@ -134,10 +138,12 @@ public class NotificationController { mNotificationManager.cancel(printJobId); } - private PendingIntent createCancelIntent(int printJobId) { + private PendingIntent createCancelIntent(PrintJobInfo printJob) { Intent intent = new Intent(mContext, NotificationBroadcastReceiver.class); - intent.setAction(INTENT_ACTION_CANCEL_PRINTJOB + "_" + String.valueOf(printJobId)); - intent.putExtra(INTENT_EXTRA_PRINTJOB_ID, printJobId); + intent.setAction(INTENT_ACTION_CANCEL_PRINTJOB + "_" + String.valueOf(printJob.getId())); + intent.putExtra(INTENT_EXTRA_PRINTJOB_ID, printJob.getId()); + intent.putExtra(INTENT_EXTRA_PRINTJOB_LABEL, printJob.getLabel()); + intent.putExtra(INTENT_EXTRA_PRINTER_NAME, printJob.getPrinterId().getPrinterName()); return PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT); } @@ -156,60 +162,68 @@ public class NotificationController { String action = intent.getAction(); if (action != null && action.startsWith(INTENT_ACTION_CANCEL_PRINTJOB)) { final int printJobId = intent.getExtras().getInt(INTENT_EXTRA_PRINTJOB_ID); - handleCancelPrintJob(context, printJobId); + String printJobLabel = intent.getExtras().getString(INTENT_EXTRA_PRINTJOB_LABEL); + String printerName = intent.getExtras().getString(INTENT_EXTRA_PRINTER_NAME); + handleCancelPrintJob(context, printJobId, printJobLabel, printerName); } else if (action != null && action.startsWith(INTENT_ACTION_RESTART_PRINTJOB)) { final int printJobId = intent.getExtras().getInt(INTENT_EXTRA_PRINTJOB_ID); handleRestartPrintJob(context, printJobId); } } - private void handleCancelPrintJob(final Context context, final int printJobId) { + private void handleCancelPrintJob(final Context context, final int printJobId, + final String printJobLabel, final String printerName) { if (DEBUG) { Log.i(LOG_TAG, "handleCancelPrintJob() printJobId:" + printJobId); } - PrintSpooler printSpooler = PrintSpooler.getInstance(context); - - final PrintJobInfo printJob = printSpooler.getPrintJobInfo(printJobId, - PrintManager.APP_ID_ANY); - - if (printJob == null || printJob.getState() == PrintJobInfo.STATE_CANCELED) { - return; - } - // Put up a notification that we are trying to cancel. NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - Notification.Builder builder = new Notification.Builder(context) // TODO: Use appropriate icon when assets are ready .setSmallIcon(android.R.drawable.ic_secure) .setContentTitle(context.getString( R.string.cancelling_notification_title_template, - printJob.getLabel())) - .setContentText(printJob.getPrinterId().getPrinterName()) - .setOngoing(true) + printJobLabel)) + .setContentText(printerName) .setWhen(System.currentTimeMillis()) + .setOngoing(true) .setShowWhen(true); - - notificationManager.notify(printJob.getId(), builder.build()); - - // We need to request the cancellation to be done by the print - // manager service since it has to communicate with the managing - // print service to request the cancellation. Also we need the - // system service to be bound to the spooler since canceling a - // print job will trigger persistence of current jobs which is - // done on another thread and until it finishes the spooler has - // to be kept around. - IPrintManager printManager = IPrintManager.Stub.asInterface( - ServiceManager.getService(Context.PRINT_SERVICE)); - - try { - printManager.cancelPrintJob(printJobId, PrintManager.APP_ID_ANY, - UserHandle.myUserId()); - } catch (RemoteException re) { - Log.i(LOG_TAG, "Error requestion print job cancellation", re); - } + notificationManager.notify(printJobId, builder.build()); + + // Call into the print manager service off the main thread since + // the print manager service may end up binding to the print spooler + // service which binding is handled on the main thread. + PowerManager powerManager = (PowerManager) + context.getSystemService(Context.POWER_SERVICE); + final WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, + LOG_TAG); + wakeLock.acquire(); + + new AsyncTask<Void, Void, Void>() { + @Override + protected Void doInBackground(Void... params) { + // We need to request the cancellation to be done by the print + // manager service since it has to communicate with the managing + // print service to request the cancellation. Also we need the + // system service to be bound to the spooler since canceling a + // print job will trigger persistence of current jobs which is + // done on another thread and until it finishes the spooler has + // to be kept around. + try { + IPrintManager printManager = IPrintManager.Stub.asInterface( + ServiceManager.getService(Context.PRINT_SERVICE)); + printManager.cancelPrintJob(printJobId, PrintManager.APP_ID_ANY, + UserHandle.myUserId()); + } catch (RemoteException re) { + Log.i(LOG_TAG, "Error requestion print job cancellation", re); + } finally { + wakeLock.release(); + } + return null; + } + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null); } private void handleRestartPrintJob(final Context context, final int printJobId) { @@ -217,29 +231,36 @@ public class NotificationController { Log.i(LOG_TAG, "handleRestartPrintJob() printJobId:" + printJobId); } - PrintSpooler printSpooler = PrintSpooler.getInstance(context); - - PrintJobInfo printJob = printSpooler.getPrintJobInfo(printJobId, - PrintManager.APP_ID_ANY); - - if (printJob == null || printJob.getState() != PrintJobInfo.STATE_FAILED) { - return; - } - - // We need to request the restart to be done by the print manager - // service since the latter must be bound to the spooler because - // restarting a print job will trigger persistence of current jobs - // which is done on another thread and until it finishes the spooler has - // to be kept around. - IPrintManager printManager = IPrintManager.Stub.asInterface( - ServiceManager.getService(Context.PRINT_SERVICE)); - - try { - printManager.restartPrintJob(printJobId, PrintManager.APP_ID_ANY, - UserHandle.myUserId()); - } catch (RemoteException re) { - Log.i(LOG_TAG, "Error requestion print job restart", re); - } + // Call into the print manager service off the main thread since + // the print manager service may end up binding to the print spooler + // service which binding is handled on the main thread. + PowerManager powerManager = (PowerManager) + context.getSystemService(Context.POWER_SERVICE); + final WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, + LOG_TAG); + wakeLock.acquire(); + + new AsyncTask<Void, Void, Void>() { + @Override + protected Void doInBackground(Void... params) { + // We need to request the restart to be done by the print manager + // service since the latter must be bound to the spooler because + // restarting a print job will trigger persistence of current jobs + // which is done on another thread and until it finishes the spooler has + // to be kept around. + try { + IPrintManager printManager = IPrintManager.Stub.asInterface( + ServiceManager.getService(Context.PRINT_SERVICE)); + printManager.restartPrintJob(printJobId, PrintManager.APP_ID_ANY, + UserHandle.myUserId()); + } catch (RemoteException re) { + Log.i(LOG_TAG, "Error requestion print job restart", re); + } finally { + wakeLock.release(); + } + return null; + } + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null); } } } diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java index 484c8a9..4a19558 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java +++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java @@ -161,7 +161,7 @@ public class PrintJobConfigActivity extends Activity { mCurrPrintAttributes.copyFrom(attributes); } - mSpooler = PrintSpooler.getInstance(this); + mSpooler = PrintSpooler.peekInstance(); mEditor = new Editor(); mDocument = new Document(); mController = new PrintController(new RemotePrintDocumentAdapter( diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java b/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java index fabd68f..0bc20a3 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java +++ b/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java @@ -19,13 +19,8 @@ package com.android.printspooler; import android.content.ComponentName; import android.content.Context; import android.os.AsyncTask; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; import android.os.ParcelFileDescriptor; -import android.os.RemoteException; import android.print.IPrintClient; -import android.print.IPrintSpoolerClient; import android.print.IPrinterDiscoveryObserver; import android.print.PageRange; import android.print.PrintAttributes; @@ -42,7 +37,6 @@ import android.util.Log; import android.util.Slog; import android.util.Xml; -import com.android.internal.os.SomeArgs; import com.android.internal.util.FastXmlSerializer; import libcore.io.IoUtils; @@ -57,9 +51,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; public class PrintSpooler { @@ -87,68 +79,38 @@ public class PrintSpooler { private final NotificationController mNotificationController; - private final Handler mHandler; + private final PrintSpoolerService mService; - private final Context mContext; - - public IPrintSpoolerClient mClient; - - public static PrintSpooler getInstance(Context context) { + public static void destroyInstance() { synchronized (sLock) { - if (sInstance == null) { - sInstance = new PrintSpooler(context); - } - return sInstance; - } - } - - private PrintSpooler(Context context) { - mContext = context; - mPersistanceManager = new PersistenceManager(context); - mNotificationController = new NotificationController(context); - mHandler = new MyHandler(context.getMainLooper()); - } - - public void setCleint(IPrintSpoolerClient client) { - synchronized (mLock) { - mClient = client; - } - } - - public void restorePersistedState() { - synchronized (mLock) { - mPersistanceManager.readStateLocked(); + sInstance = null; } } - public void onReqeustUpdatePrinters(List<PrinterId> printers) { - synchronized (mLock) { - SomeArgs args = SomeArgs.obtain(); - args.arg1 = mClient; - args.arg2 = printers; - mHandler.obtainMessage(MyHandler.MSG_ON_REQUEST_UPDATE_PRINTERS, - args).sendToTarget(); + public static void createInstance(PrintSpoolerService service) { + synchronized (sLock) { + sInstance = new PrintSpooler(service); } } - public void startPrinterDiscovery(IPrinterDiscoveryObserver observer) { - synchronized (mLock) { - SomeArgs args = SomeArgs.obtain(); - args.arg1 = mClient; - args.arg2 = observer; - mHandler.obtainMessage(MyHandler.MSG_ON_START_PRINTER_DISCOVERY, - args).sendToTarget(); + public static PrintSpooler peekInstance() { + synchronized (sLock) { + return sInstance; } } - public void stopPrinterDiscovery() { + private PrintSpooler(PrintSpoolerService service) { + mService = service; + mPersistanceManager = new PersistenceManager(service); + mNotificationController = new NotificationController(service); synchronized (mLock) { - mHandler.obtainMessage(MyHandler.MSG_ON_STOP_PRINTER_DISCOVERY, - mClient).sendToTarget(); + mPersistanceManager.readStateLocked(); + handleReadPrintJobsLocked(); } } - public List<PrintJobInfo> getPrintJobInfos(ComponentName componentName, int state, int appId) { + public List<PrintJobInfo> getPrintJobInfos(ComponentName componentName, + int state, int appId) { List<PrintJobInfo> foundPrintJobs = null; synchronized (mLock) { final int printJobCount = mPrintJobs.size(); @@ -207,79 +169,48 @@ public class PrintSpooler { } } - public void notifyClientForActivteJobs() { - IPrintSpoolerClient client = null; - Map<ComponentName, List<PrintJobInfo>> activeJobsPerServiceMap = - new HashMap<ComponentName, List<PrintJobInfo>>(); + private void handleReadPrintJobsLocked() { + final int printJobCount = mPrintJobs.size(); + for (int i = 0; i < printJobCount; i++) { + PrintJobInfo printJob = mPrintJobs.get(i); - synchronized (mLock) { - if (mClient == null) { - throw new IllegalStateException("Client cannot be null."); - } - client = mClient; + // Update the notification. + mNotificationController.onPrintJobStateChanged(printJob); - final int printJobCount = mPrintJobs.size(); - for (int i = 0; i < printJobCount; i++) { - PrintJobInfo printJob = mPrintJobs.get(i); - switch (printJob.getState()) { - case PrintJobInfo.STATE_CREATED: { - /* skip - not ready to be handled by a service */ - } break; + //TODO: Figure out what the right policy for read print jobs is. - case PrintJobInfo.STATE_QUEUED: - case PrintJobInfo.STATE_STARTED: { - ComponentName service = printJob.getPrinterId().getServiceName(); - List<PrintJobInfo> jobsPerService = activeJobsPerServiceMap.get(service); - if (jobsPerService == null) { - jobsPerService = new ArrayList<PrintJobInfo>(); - activeJobsPerServiceMap.put(service, jobsPerService); - } - jobsPerService.add(printJob); - } break; + switch (printJob.getState()) { + case PrintJobInfo.STATE_QUEUED: { + // Notify that we have a queued job. + mService.onPrintJobQueued(new PrintJobInfo(printJob)); + } break; - default: { - ComponentName service = printJob.getPrinterId().getServiceName(); - if (!activeJobsPerServiceMap.containsKey(service)) { - activeJobsPerServiceMap.put(service, null); - } - } - } + case PrintJobInfo.STATE_STARTED: { + // We really want to restart this print job. + setPrintJobState(printJob.getId(), PrintJobInfo.STATE_QUEUED, null); + } break; } } + } - boolean allPrintJobsHandled = true; - - for (Map.Entry<ComponentName, List<PrintJobInfo>> entry - : activeJobsPerServiceMap.entrySet()) { - ComponentName service = entry.getKey(); - List<PrintJobInfo> printJobs = entry.getValue(); - - if (printJobs != null) { - allPrintJobsHandled = false; - final int printJobCount = printJobs.size(); - for (int i = 0; i < printJobCount; i++) { - PrintJobInfo printJob = printJobs.get(i); - if (printJob.getState() == PrintJobInfo.STATE_QUEUED) { - SomeArgs args = SomeArgs.obtain(); - args.arg1 = client; - args.arg2 = new PrintJobInfo(printJob); - mHandler.obtainMessage(MyHandler.MSG_ON_PRINT_JOB_QUEUED, - args).sendToTarget(); - } - } - } else { - SomeArgs args = SomeArgs.obtain(); - args.arg1 = client; - args.arg2 = service; - mHandler.obtainMessage(MyHandler.MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED, - args).sendToTarget(); + public void checkAllPrintJobsHandled() { + synchronized (mLock) { + if (!hasActivePrintJobsLocked()) { + notifyOnAllPrintJobsHandled(); } } + } - if (allPrintJobsHandled) { - mHandler.obtainMessage(MyHandler.MSG_ON_ALL_PRINT_JOBS_HANDLED, - client).sendToTarget(); - } + public void startPrinterDiscovery(IPrinterDiscoveryObserver observer) { + mService.startPrinterDiscovery(observer); + } + + public void stopPrinterDiscovery() { + mService.stopPrinterDiscovery(); + } + + public void onReqeustUpdatePrinters(List<PrinterId> printerIds) { + mService.onReqeustUpdatePrinters(printerIds); } private int generatePrintJobIdLocked() { @@ -341,7 +272,7 @@ public class PrintSpooler { } public File generateFileForPrintJob(int printJobId) { - return new File(mContext.getFilesDir(), "print_job_" + return new File(mService.getFilesDir(), "print_job_" + printJobId + "." + PRINT_FILE_EXTENSION); } @@ -365,88 +296,67 @@ public class PrintSpooler { boolean success = false; synchronized (mLock) { - if (mClient == null) { - throw new IllegalStateException("Client cannot be null."); - } - PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); if (printJob != null) { success = true; - final int oldState = printJob.getState(); printJob.setState(state); printJob.setFailureReason(error); - mNotificationController.onPrintJobStateChanged(printJob, oldState); + mNotificationController.onPrintJobStateChanged(printJob); if (DEBUG_PRINT_JOB_LIFECYCLE) { Slog.i(LOG_TAG, "[STATE CHANGED] " + printJob); } - // TODO: Update notifications. switch (state) { case PrintJobInfo.STATE_COMPLETED: - case PrintJobInfo.STATE_CANCELED: { + case PrintJobInfo.STATE_CANCELED: removePrintJobLocked(printJob); - - // No printer means creation of a print job was cancelled, - // therefore the state of the spooler did not change and no - // notifications are needed. We also do not need to persist - // the state. + // $fall-through$ + case PrintJobInfo.STATE_FAILED: { PrinterId printerId = printJob.getPrinterId(); - if (printerId == null) { - return true; - } - - ComponentName service = printerId.getServiceName(); - if (!hasActivePrintJobsForServiceLocked(service)) { - SomeArgs args = SomeArgs.obtain(); - args.arg1 = mClient; - args.arg2 = service; - mHandler.obtainMessage( - MyHandler.MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED, - args).sendToTarget(); - } - - if (!hasActivePrintJobsLocked()) { - mHandler.obtainMessage(MyHandler.MSG_ON_ALL_PRINT_JOBS_HANDLED, - mClient).sendToTarget(); + if (printerId != null) { + ComponentName service = printerId.getServiceName(); + if (!hasActivePrintJobsForServiceLocked(service)) { + mService.onAllPrintJobsForServiceHandled(service); + } } } break; case PrintJobInfo.STATE_QUEUED: { - SomeArgs args = SomeArgs.obtain(); - args.arg1 = mClient; - args.arg2 = new PrintJobInfo(printJob); - mHandler.obtainMessage(MyHandler.MSG_ON_PRINT_JOB_QUEUED, - args).sendToTarget(); + mService.onPrintJobQueued(new PrintJobInfo(printJob)); } break; } if (shouldPersistPrintJob(printJob)) { mPersistanceManager.writeStateLocked(); } + + if (!hasActivePrintJobsLocked()) { + notifyOnAllPrintJobsHandled(); + } } } return success; } - private boolean hasActivePrintJobsLocked() { + public boolean hasActivePrintJobsLocked() { final int printJobCount = mPrintJobs.size(); for (int i = 0; i < printJobCount; i++) { PrintJobInfo printJob = mPrintJobs.get(i); - if (!isActiveState(printJob.getState())) { + if (isActiveState(printJob.getState())) { return true; } } return false; } - private boolean hasActivePrintJobsForServiceLocked(ComponentName service) { + public boolean hasActivePrintJobsForServiceLocked(ComponentName service) { final int printJobCount = mPrintJobs.size(); for (int i = 0; i < printJobCount; i++) { PrintJobInfo printJob = mPrintJobs.get(i); - if (!isActiveState(printJob.getState()) + if (isActiveState(printJob.getState()) && printJob.getPrinterId().getServiceName().equals(service)) { return true; } @@ -455,9 +365,9 @@ public class PrintSpooler { } private static boolean isActiveState(int printJobState) { - return printJobState != PrintJobInfo.STATE_CREATED - || printJobState != PrintJobInfo.STATE_QUEUED - || printJobState != PrintJobInfo.STATE_STARTED; + return printJobState == PrintJobInfo.STATE_CREATED + || printJobState == PrintJobInfo.STATE_QUEUED + || printJobState == PrintJobInfo.STATE_STARTED; } public boolean setPrintJobTag(int printJobId, String tag) { @@ -531,6 +441,20 @@ public class PrintSpooler { return printJob.getState() >= PrintJobInfo.STATE_QUEUED; } + private void notifyOnAllPrintJobsHandled() { + // This has to run on the tread that is persisting the current state + // since this call may result in the system unbinding from the spooler + // and as a result the spooler process may get killed before the write + // completes. + new AsyncTask<Void, Void, Void>() { + @Override + protected Void doInBackground(Void... params) { + mService.onAllPrintJobsHandled(); + return null; + } + }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null); + } + private final class PersistenceManager { private static final String PERSIST_FILE_NAME = "print_spooler_state.xml"; @@ -1056,108 +980,4 @@ public class PrintSpooler { return true; } } - - private final class MyHandler extends Handler { - public static final int MSG_ON_START_PRINTER_DISCOVERY = 1; - public static final int MSG_ON_STOP_PRINTER_DISCOVERY = 2; - public static final int MSG_ON_PRINT_JOB_QUEUED = 3; - public static final int MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED = 4; - public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 5; - public static final int MSG_ON_REQUEST_UPDATE_PRINTERS = 6; - - public MyHandler(Looper looper) { - super(looper, null, false); - } - - @Override - @SuppressWarnings("unchecked") - public void handleMessage(Message message) { - switch (message.what) { - case MSG_ON_START_PRINTER_DISCOVERY: { - SomeArgs args = (SomeArgs) message.obj; - IPrintSpoolerClient client = (IPrintSpoolerClient) args.arg1; - IPrinterDiscoveryObserver observer = (IPrinterDiscoveryObserver) args.arg2; - args.recycle(); - if (client != null) { - try { - client.onStartPrinterDiscovery(observer); - } catch (RemoteException re) { - Log.e(LOG_TAG, "Error notifying start printer discovery.", re); - } - } - } break; - - case MSG_ON_STOP_PRINTER_DISCOVERY: { - IPrintSpoolerClient client = (IPrintSpoolerClient) message.obj; - if (client != null) { - try { - client.onStopPrinterDiscovery(); - } catch (RemoteException re) { - Log.e(LOG_TAG, "Error notifying stop printer discovery.", re); - } - } - } break; - - case MSG_ON_PRINT_JOB_QUEUED: { - SomeArgs args = (SomeArgs) message.obj; - IPrintSpoolerClient client = (IPrintSpoolerClient) args.arg1; - PrintJobInfo printJob = (PrintJobInfo) args.arg2; - args.recycle(); - if (client != null) { - try { - client.onPrintJobQueued(printJob); - } catch (RemoteException re) { - Slog.e(LOG_TAG, "Error notify for a queued print job.", re); - } - } - } break; - - case MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED: { - SomeArgs args = (SomeArgs) message.obj; - IPrintSpoolerClient client = (IPrintSpoolerClient) args.arg1; - ComponentName service = (ComponentName) args.arg2; - args.recycle(); - if (client != null) { - try { - client.onAllPrintJobsForServiceHandled(service); - } catch (RemoteException re) { - Slog.e(LOG_TAG, "Error notify for all print jobs per service" - + " handled.", re); - } - } - } break; - - case MSG_ON_ALL_PRINT_JOBS_HANDLED: { - final IPrintSpoolerClient client = (IPrintSpoolerClient) message.obj; - // This has to run on the tread that is persisting the current state - // since this call may result in the system unbinding from the spooler - // and as a result the spooler process may get killed before the write - // completes. - new AsyncTask<Void, Void, Void>() { - @Override - protected Void doInBackground(Void... params) { - try { - client.onAllPrintJobsHandled(); - } catch (RemoteException re) { - Slog.e(LOG_TAG, "Error notify for all print job handled.", re); - } - return null; - } - }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null); - } break; - - case MSG_ON_REQUEST_UPDATE_PRINTERS: { - SomeArgs args = (SomeArgs) message.obj; - IPrintSpoolerClient client = (IPrintSpoolerClient) args.arg1; - List<PrinterId> printerIds = (List<PrinterId>) args.arg2; - args.recycle(); - try { - client.onRequestUpdatePrinters(printerIds); - } catch (RemoteException re) { - Slog.e(LOG_TAG, "Error requesting to update pritners.", re); - } - } break; - } - } - } } diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java index 58853f7..e5153e7 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java +++ b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java @@ -16,8 +16,6 @@ package com.android.printspooler; -import java.util.List; - import android.app.PendingIntent; import android.app.Service; import android.content.ComponentName; @@ -29,44 +27,48 @@ import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.RemoteException; -import android.print.IPrintDocumentAdapter; import android.print.IPrintClient; -import android.print.IPrintSpoolerClient; +import android.print.IPrintDocumentAdapter; import android.print.IPrintSpooler; import android.print.IPrintSpoolerCallbacks; +import android.print.IPrintSpoolerClient; +import android.print.IPrinterDiscoveryObserver; import android.print.PrintAttributes; import android.print.PrintJobInfo; +import android.print.PrinterId; +import android.util.Log; import android.util.Slog; import com.android.internal.os.SomeArgs; +import java.util.List; + /** * Service for exposing some of the {@link PrintSpooler} functionality to * another process. */ public final class PrintSpoolerService extends Service { + private static final long CHECK_ALL_PRINTJOBS_HANDLED_DELAY = 5000; + private static final String LOG_TAG = "PrintSpoolerService"; private Intent mStartPrintJobConfigActivityIntent; - private PrintSpooler mSpooler; + private IPrintSpoolerClient mClient; - private Handler mHanlder; + private Handler mHandler; @Override public void onCreate() { super.onCreate(); mStartPrintJobConfigActivityIntent = new Intent(PrintSpoolerService.this, PrintJobConfigActivity.class); - mSpooler = PrintSpooler.getInstance(this); - mHanlder = new MyHandler(getMainLooper()); + mHandler = new MyHandler(getMainLooper()); } @Override public IBinder onBind(Intent intent) { - mSpooler.restorePersistedState(); - return new IPrintSpooler.Stub() { @Override public void getPrintJobInfos(IPrintSpoolerCallbacks callback, @@ -74,7 +76,8 @@ public final class PrintSpoolerService extends Service { throws RemoteException { List<PrintJobInfo> printJobs = null; try { - printJobs = mSpooler.getPrintJobInfos(componentName, state, appId); + printJobs = PrintSpooler.peekInstance().getPrintJobInfos( + componentName, state, appId); } finally { callback.onGetPrintJobInfosResult(printJobs, sequence); } @@ -85,7 +88,7 @@ public final class PrintSpoolerService extends Service { int appId, int sequence) throws RemoteException { PrintJobInfo printJob = null; try { - printJob = mSpooler.getPrintJobInfo(printJobId, appId); + printJob = PrintSpooler.peekInstance().getPrintJobInfo(printJobId, appId); } finally { callback.onGetPrintJobInfoResult(printJob, sequence); } @@ -99,7 +102,7 @@ public final class PrintSpoolerService extends Service { throws RemoteException { PrintJobInfo printJob = null; try { - printJob = mSpooler.createPrintJob(printJobName, client, + printJob = PrintSpooler.peekInstance().createPrintJob(printJobName, client, attributes, appId); if (printJob != null) { Intent intent = mStartPrintJobConfigActivityIntent; @@ -116,7 +119,8 @@ public final class PrintSpoolerService extends Service { SomeArgs args = SomeArgs.obtain(); args.arg1 = client; args.arg2 = sender; - mHanlder.obtainMessage(0, args).sendToTarget(); + mHandler.obtainMessage(MyHandler.MSG_START_PRINT_JOB_CONFIG_ACTIVITY, + args).sendToTarget(); } } finally { callback.onCreatePrintJobResult(printJob, sequence); @@ -128,7 +132,8 @@ public final class PrintSpoolerService extends Service { IPrintSpoolerCallbacks callback, int sequece) throws RemoteException { boolean success = false; try { - success = mSpooler.setPrintJobState(printJobId, state, error); + success = PrintSpooler.peekInstance().setPrintJobState( + printJobId, state, error); } finally { callback.onSetPrintJobStateResult(success, sequece); } @@ -136,11 +141,10 @@ public final class PrintSpoolerService extends Service { @Override public void setPrintJobTag(int printJobId, String tag, - IPrintSpoolerCallbacks callback, int sequece) - throws RemoteException { + IPrintSpoolerCallbacks callback, int sequece) throws RemoteException { boolean success = false; try { - success = mSpooler.setPrintJobTag(printJobId, tag); + success = PrintSpooler.peekInstance().setPrintJobTag(printJobId, tag); } finally { callback.onSetPrintJobTagResult(success, sequece); } @@ -148,37 +152,158 @@ public final class PrintSpoolerService extends Service { @Override public void writePrintJobData(ParcelFileDescriptor fd, int printJobId) { - mSpooler.writePrintJobData(fd, printJobId); - } - - @Override - public void setClient(IPrintSpoolerClient client) { - mSpooler.setCleint(client); + PrintSpooler.peekInstance().writePrintJobData(fd, printJobId); } @Override - public void notifyClientForActivteJobs() { - mSpooler.notifyClientForActivteJobs(); + public void setClient(IPrintSpoolerClient client) { + mHandler.obtainMessage(MyHandler.MSG_SET_CLIENT, client).sendToTarget(); } }; } - private static final class MyHandler extends Handler { + public void onPrintJobQueued(PrintJobInfo printJob) { + mHandler.obtainMessage(MyHandler.MSG_ON_PRINT_JOB_QUEUED, + printJob).sendToTarget(); + } + + public void onReqeustUpdatePrinters(List<PrinterId> printers) { + mHandler.obtainMessage(MyHandler.MSG_ON_REQUEST_UPDATE_PRINTERS, + printers).sendToTarget(); + } + + public void startPrinterDiscovery(IPrinterDiscoveryObserver observer) { + mHandler.obtainMessage(MyHandler.MSG_ON_START_PRINTER_DISCOVERY, + observer).sendToTarget(); + } + + public void stopPrinterDiscovery() { + mHandler.sendEmptyMessage(MyHandler.MSG_ON_STOP_PRINTER_DISCOVERY); + } + + public void onAllPrintJobsForServiceHandled(ComponentName service) { + mHandler.obtainMessage(MyHandler.MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED, + service).sendToTarget(); + } + + public void onAllPrintJobsHandled() { + mHandler.sendEmptyMessage(MyHandler.MSG_ON_ALL_PRINT_JOBS_HANDLED); + } + + private final class MyHandler extends Handler { + public static final int MSG_SET_CLIENT = 1; + public static final int MSG_START_PRINT_JOB_CONFIG_ACTIVITY = 2; + public static final int MSG_ON_START_PRINTER_DISCOVERY = 3; + public static final int MSG_ON_STOP_PRINTER_DISCOVERY = 4; + public static final int MSG_ON_PRINT_JOB_QUEUED = 5; + public static final int MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED = 6; + public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 7; + public static final int MSG_ON_REQUEST_UPDATE_PRINTERS = 8; + public static final int MSG_CHECK_ALL_PRINTJOBS_HANDLED = 9; public MyHandler(Looper looper) { - super(looper, null, true); + super(looper, null, false); } @Override + @SuppressWarnings("unchecked") public void handleMessage(Message message) { - SomeArgs args = (SomeArgs) message.obj; - IPrintClient client = (IPrintClient) args.arg1; - IntentSender sender = (IntentSender) args.arg2; - args.recycle(); - try { - client.startPrintJobConfigActivity(sender); - } catch (RemoteException re) { - Slog.i(LOG_TAG, "Error starting print job config activity!", re); + switch (message.what) { + case MSG_SET_CLIENT: { + mClient = (IPrintSpoolerClient) message.obj; + if (mClient != null) { + PrintSpooler.createInstance(PrintSpoolerService.this); + mHandler.sendEmptyMessageDelayed( + MyHandler.MSG_CHECK_ALL_PRINTJOBS_HANDLED, + CHECK_ALL_PRINTJOBS_HANDLED_DELAY); + } else { + PrintSpooler.destroyInstance(); + } + } break; + + case MSG_START_PRINT_JOB_CONFIG_ACTIVITY: { + SomeArgs args = (SomeArgs) message.obj; + IPrintClient client = (IPrintClient) args.arg1; + IntentSender sender = (IntentSender) args.arg2; + args.recycle(); + try { + client.startPrintJobConfigActivity(sender); + } catch (RemoteException re) { + Slog.i(LOG_TAG, "Error starting print job config activity!", re); + } + } break; + + case MSG_ON_START_PRINTER_DISCOVERY: { + IPrinterDiscoveryObserver observer = (IPrinterDiscoveryObserver) message.obj; + if (mClient != null) { + try { + mClient.onStartPrinterDiscovery(observer); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error notifying start printer discovery.", re); + } + } + } break; + + case MSG_ON_STOP_PRINTER_DISCOVERY: { + if (mClient != null) { + try { + mClient.onStopPrinterDiscovery(); + } catch (RemoteException re) { + Log.e(LOG_TAG, "Error notifying stop printer discovery.", re); + } + } + } break; + + case MSG_ON_PRINT_JOB_QUEUED: { + PrintJobInfo printJob = (PrintJobInfo) message.obj; + if (mClient != null) { + try { + mClient.onPrintJobQueued(printJob); + } catch (RemoteException re) { + Slog.e(LOG_TAG, "Error notify for a queued print job.", re); + } + } + } break; + + case MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED: { + ComponentName service = (ComponentName) message.obj; + if (mClient != null) { + try { + mClient.onAllPrintJobsForServiceHandled(service); + } catch (RemoteException re) { + Slog.e(LOG_TAG, "Error notify for all print jobs per service" + + " handled.", re); + } + } + } break; + + case MSG_ON_ALL_PRINT_JOBS_HANDLED: { + if (mClient != null) { + try { + mClient.onAllPrintJobsHandled(); + } catch (RemoteException re) { + Slog.e(LOG_TAG, "Error notify for all print job handled.", re); + } + } + } break; + + case MSG_ON_REQUEST_UPDATE_PRINTERS: { + List<PrinterId> printerIds = (List<PrinterId>) message.obj; + if (mClient != null) { + try { + mClient.onRequestUpdatePrinters(printerIds); + } catch (RemoteException re) { + Slog.e(LOG_TAG, "Error requesting to update pritners.", re); + } + } + } break; + + case MSG_CHECK_ALL_PRINTJOBS_HANDLED: { + PrintSpooler spooler = PrintSpooler.peekInstance(); + if (spooler != null) { + spooler.checkAllPrintJobsHandled(); + } + } break; } } } |