From 835835ee6f913408ac91678d6056896a2c5b25e3 Mon Sep 17 00:00:00 2001 From: Svetoslav Ganov Date: Sun, 4 Aug 2013 20:17:52 -0700 Subject: [PATCH] Polish the print spooler loading of stored print jobs. 1. The singleton print spooler isntance is created when the print spooler service gets a connection to the system and is destroyed when this connection is removed. Note that if the spooler has work, then the connection to the system will not be removed. When the spooler is created, it reads the stored state and notifies the system which in turn dispatches this to the print services. When the system connects to the spooler and passes it a connection, we schedule a delayed check whether there is work for the spooler. We do not handle this immediately to avoid intermitted spinning on and off of the spooler process if a client makes a sequence of queries while the spooler has really no work. 2. Fixed a bug in the NotificationManagerService where adding a notification and removing it immediately after that does not remove the notification. The code that is adding a notification is run on a handler thread while the code to remove it on the calling thread. This creates a race and erroneous results. Now the removal is also scheduled on the handler. 3. Many small fixes here and there. Change-Id: I6415c253139fa6616393fbe23c659d031a29e1f6 --- core/java/android/print/IPrintSpooler.aidl | 1 - .../printspooler/NotificationController.java | 153 ++++---- .../printspooler/PrintJobConfigActivity.java | 2 +- .../android/printspooler/PrintSpooler.java | 364 +++++------------- .../printspooler/PrintSpoolerService.java | 197 ++++++++-- .../server/NotificationManagerService.java | 48 ++- .../server/print/PrintManagerService.java | 8 +- .../server/print/RemotePrintService.java | 8 +- .../server/print/RemotePrintSpooler.java | 51 ++- .../com/android/server/print/UserState.java | 2 +- 10 files changed, 403 insertions(+), 431 deletions(-) diff --git a/core/java/android/print/IPrintSpooler.aidl b/core/java/android/print/IPrintSpooler.aidl index 428f9722ec648..81781801d0db9 100644 --- a/core/java/android/print/IPrintSpooler.aidl +++ b/core/java/android/print/IPrintSpooler.aidl @@ -46,5 +46,4 @@ oneway interface IPrintSpooler { int sequence); void writePrintJobData(in ParcelFileDescriptor fd, int printJobId); void setClient(IPrintSpoolerClient client); - void notifyClientForActivteJobs(); } diff --git a/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java b/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java index e4de4b85273bf..14a96c946182e 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(printJobId, builder.build()); - notificationManager.notify(printJob.getId(), 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(); - // 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); - } + new AsyncTask() { + @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); + // 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(); - 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); - } + new AsyncTask() { + @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 484c8a96f3d1e..4a19558336102 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 fabd68f9683b8..0bc20a3f2f2c3 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) { + sInstance = null; + } + } + + public static void createInstance(PrintSpoolerService service) { + synchronized (sLock) { + sInstance = new PrintSpooler(service); + } + } + + public static PrintSpooler peekInstance() { 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() { + private PrintSpooler(PrintSpoolerService service) { + mService = service; + mPersistanceManager = new PersistenceManager(service); + mNotificationController = new NotificationController(service); synchronized (mLock) { mPersistanceManager.readStateLocked(); + handleReadPrintJobsLocked(); } } - public void onReqeustUpdatePrinters(List printers) { - synchronized (mLock) { - SomeArgs args = SomeArgs.obtain(); - args.arg1 = mClient; - args.arg2 = printers; - mHandler.obtainMessage(MyHandler.MSG_ON_REQUEST_UPDATE_PRINTERS, - args).sendToTarget(); - } - } - - 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 void stopPrinterDiscovery() { - synchronized (mLock) { - mHandler.obtainMessage(MyHandler.MSG_ON_STOP_PRINTER_DISCOVERY, - mClient).sendToTarget(); - } - } - - public List getPrintJobInfos(ComponentName componentName, int state, int appId) { + public List getPrintJobInfos(ComponentName componentName, + int state, int appId) { List foundPrintJobs = null; synchronized (mLock) { final int printJobCount = mPrintJobs.size(); @@ -207,79 +169,48 @@ public class PrintSpooler { } } - public void notifyClientForActivteJobs() { - IPrintSpoolerClient client = null; - Map> activeJobsPerServiceMap = - new HashMap>(); + private void handleReadPrintJobsLocked() { + final int printJobCount = mPrintJobs.size(); + for (int i = 0; i < printJobCount; i++) { + PrintJobInfo printJob = mPrintJobs.get(i); + // Update the notification. + mNotificationController.onPrintJobStateChanged(printJob); + + //TODO: Figure out what the right policy for read print jobs is. + + switch (printJob.getState()) { + case PrintJobInfo.STATE_QUEUED: { + // Notify that we have a queued job. + mService.onPrintJobQueued(new PrintJobInfo(printJob)); + } break; + + case PrintJobInfo.STATE_STARTED: { + // We really want to restart this print job. + setPrintJobState(printJob.getId(), PrintJobInfo.STATE_QUEUED, null); + } break; + } + } + } + + public void checkAllPrintJobsHandled() { synchronized (mLock) { - if (mClient == null) { - throw new IllegalStateException("Client cannot be null."); - } - client = mClient; - - 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; - - case PrintJobInfo.STATE_QUEUED: - case PrintJobInfo.STATE_STARTED: { - ComponentName service = printJob.getPrinterId().getServiceName(); - List jobsPerService = activeJobsPerServiceMap.get(service); - if (jobsPerService == null) { - jobsPerService = new ArrayList(); - activeJobsPerServiceMap.put(service, jobsPerService); - } - jobsPerService.add(printJob); - } break; - - default: { - ComponentName service = printJob.getPrinterId().getServiceName(); - if (!activeJobsPerServiceMap.containsKey(service)) { - activeJobsPerServiceMap.put(service, null); - } - } - } + if (!hasActivePrintJobsLocked()) { + notifyOnAllPrintJobsHandled(); } } + } - boolean allPrintJobsHandled = true; + public void startPrinterDiscovery(IPrinterDiscoveryObserver observer) { + mService.startPrinterDiscovery(observer); + } - for (Map.Entry> entry - : activeJobsPerServiceMap.entrySet()) { - ComponentName service = entry.getKey(); - List printJobs = entry.getValue(); + public void stopPrinterDiscovery() { + mService.stopPrinterDiscovery(); + } - 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(); - } - } - - if (allPrintJobsHandled) { - mHandler.obtainMessage(MyHandler.MSG_ON_ALL_PRINT_JOBS_HANDLED, - client).sendToTarget(); - } + public void onReqeustUpdatePrinters(List 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() { + @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() { - @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 printerIds = (List) 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 58853f79867e3..e5153e759263a 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 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); + PrintSpooler.peekInstance().writePrintJobData(fd, printJobId); } @Override - public void setClient(IPrintSpoolerClient client) { - mSpooler.setCleint(client); - } - - @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 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 printerIds = (List) 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; } } } diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index 1e8a589992d1c..b881934879d61 100644 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -2047,29 +2047,39 @@ public class NotificationManagerService extends INotificationManager.Stub * Cancels a notification ONLY if it has all of the {@code mustHaveFlags} * and none of the {@code mustNotHaveFlags}. */ - private void cancelNotification(String pkg, String tag, int id, int mustHaveFlags, - int mustNotHaveFlags, boolean sendDelete, int userId) { - EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL, pkg, id, tag, userId, - mustHaveFlags, mustNotHaveFlags); + private void cancelNotification(final String pkg, final String tag, final int id, + final int mustHaveFlags, final int mustNotHaveFlags, final boolean sendDelete, + final int userId) { + // In enqueueNotificationInternal notifications are added by scheduling the + // work on the worker handler. Hence, we also schedule the cancel on this + // handler to avoid a scenario where an add notification call followed by a + // remove notification call ends up in not removing the notification. + mHandler.post(new Runnable() { + @Override + public void run() { + EventLog.writeEvent(EventLogTags.NOTIFICATION_CANCEL, pkg, id, tag, userId, + mustHaveFlags, mustNotHaveFlags); - synchronized (mNotificationList) { - int index = indexOfNotificationLocked(pkg, tag, id, userId); - if (index >= 0) { - NotificationRecord r = mNotificationList.get(index); + synchronized (mNotificationList) { + int index = indexOfNotificationLocked(pkg, tag, id, userId); + if (index >= 0) { + NotificationRecord r = mNotificationList.get(index); - if ((r.getNotification().flags & mustHaveFlags) != mustHaveFlags) { - return; + if ((r.getNotification().flags & mustHaveFlags) != mustHaveFlags) { + return; + } + if ((r.getNotification().flags & mustNotHaveFlags) != 0) { + return; + } + + mNotificationList.remove(index); + + cancelNotificationLocked(r, sendDelete); + updateLightsLocked(); + } } - if ((r.getNotification().flags & mustNotHaveFlags) != 0) { - return; - } - - mNotificationList.remove(index); - - cancelNotificationLocked(r, sendDelete); - updateLightsLocked(); } - } + }); } /** diff --git a/services/java/com/android/server/print/PrintManagerService.java b/services/java/com/android/server/print/PrintManagerService.java index 41399d874d38d..8ee2fea27a13b 100644 --- a/services/java/com/android/server/print/PrintManagerService.java +++ b/services/java/com/android/server/print/PrintManagerService.java @@ -68,7 +68,7 @@ public final class PrintManagerService extends IPrintManager.Stub { synchronized (mLock) { UserState userState = getCurrentUserStateLocked(); userState.updateIfNeededLocked(); - userState.getSpoolerLocked().notifyClientForActivteJobs(); + userState.getSpoolerLocked().start(); } } }); @@ -144,7 +144,7 @@ public final class PrintManagerService extends IPrintManager.Stub { } final long identity = Binder.clearCallingIdentity(); try { - PrintJobInfo printJobInfo = getPrintJobInfo(printJobId, resolvedAppId, resolvedUserId); + PrintJobInfo printJobInfo = spooler.getPrintJobInfo(printJobId, resolvedAppId); if (printJobInfo == null) { return; } @@ -152,7 +152,7 @@ public final class PrintManagerService extends IPrintManager.Stub { ComponentName printServiceName = printJobInfo.getPrinterId().getServiceName(); RemotePrintService printService = null; synchronized (mLock) { - printService = userState.getActiveServices().get(printServiceName); + printService = userState.getActiveServicesLocked().get(printServiceName); } if (printService == null) { return; @@ -328,7 +328,7 @@ public final class PrintManagerService extends IPrintManager.Stub { mCurrentUserId = newUserId; UserState userState = getCurrentUserStateLocked(); userState.updateIfNeededLocked(); - userState.getSpoolerLocked().notifyClientForActivteJobs(); + userState.getSpoolerLocked().start(); } } diff --git a/services/java/com/android/server/print/RemotePrintService.java b/services/java/com/android/server/print/RemotePrintService.java index 5aa9952bd5365..28a7362bc6cd0 100644 --- a/services/java/com/android/server/print/RemotePrintService.java +++ b/services/java/com/android/server/print/RemotePrintService.java @@ -228,19 +228,19 @@ final class RemotePrintService implements DeathRecipient { printerIds).sendToTarget(); } - private void handleReqeustUpdatePritners(final List printerIds) { + private void handleReqeustUpdatePrinters(final List printerIds) { throwIfDestroyed(); if (!isBound()) { ensureBound(); mPendingCommands.add(new Runnable() { @Override public void run() { - handleReqeustUpdatePritners(printerIds); + handleReqeustUpdatePrinters(printerIds); } }); } else { if (DEBUG) { - Slog.i(LOG_TAG, "[user: " + mUserId + "] handleReqeustUpdatePritners()"); + Slog.i(LOG_TAG, "[user: " + mUserId + "] handleReqeustUpdatePrinters()"); } try { mPrintService.onRequestUpdatePrinters(printerIds); @@ -367,7 +367,7 @@ final class RemotePrintService implements DeathRecipient { case MSG_ON_REQUEST_UPDATE_PRINTERS: { List printerIds = (List) message.obj; - handleReqeustUpdatePritners(printerIds); + handleReqeustUpdatePrinters(printerIds); } break; case MSG_ON_STOP_PRINTER_DISCOVERY: { diff --git a/services/java/com/android/server/print/RemotePrintSpooler.java b/services/java/com/android/server/print/RemotePrintSpooler.java index 4e561bb2b42f2..3a96a5bc74f22 100644 --- a/services/java/com/android/server/print/RemotePrintSpooler.java +++ b/services/java/com/android/server/print/RemotePrintSpooler.java @@ -116,9 +116,6 @@ final class RemotePrintSpooler { throwIfDestroyedLocked(); mCanUnbind = false; } - if (DEBUG) { - Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] getPrintJobInfos()"); - } try { return mGetPrintJobInfosCaller.getPrintJobInfos(getRemoteInstanceLazy(), componentName, state, appId); @@ -127,6 +124,9 @@ final class RemotePrintSpooler { } 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(); @@ -142,9 +142,6 @@ final class RemotePrintSpooler { throwIfDestroyedLocked(); mCanUnbind = false; } - if (DEBUG) { - Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] createPrintJob()"); - } try { return mCreatePrintJobCaller.createPrintJob(getRemoteInstanceLazy(), printJobName, client, documentAdapter, attributes, appId); @@ -153,6 +150,9 @@ final class RemotePrintSpooler { } 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(); @@ -167,9 +167,6 @@ final class RemotePrintSpooler { throwIfDestroyedLocked(); mCanUnbind = false; } - if (DEBUG) { - Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] writePrintJobData()"); - } try { getRemoteInstanceLazy().writePrintJobData(fd, printJobId); } catch (RemoteException re) { @@ -177,6 +174,9 @@ final class RemotePrintSpooler { } 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); @@ -193,9 +193,6 @@ final class RemotePrintSpooler { throwIfDestroyedLocked(); mCanUnbind = false; } - if (DEBUG) { - Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] getPrintJobInfo()"); - } try { return mGetPrintJobInfoCaller.getPrintJobInfo(getRemoteInstanceLazy(), printJobId, appId); @@ -204,6 +201,9 @@ final class RemotePrintSpooler { } 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(); @@ -218,9 +218,6 @@ final class RemotePrintSpooler { throwIfDestroyedLocked(); mCanUnbind = false; } - if (DEBUG) { - Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setPrintJobState()"); - } try { return mSetPrintJobStatusCaller.setPrintJobState(getRemoteInstanceLazy(), printJobId, state, error); @@ -229,6 +226,9 @@ final class RemotePrintSpooler { } 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(); @@ -243,9 +243,6 @@ final class RemotePrintSpooler { throwIfDestroyedLocked(); mCanUnbind = false; } - if (DEBUG) { - Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setPrintJobTag()"); - } try { return mSetPrintJobTagCaller.setPrintJobTag(getRemoteInstanceLazy(), printJobId, tag); @@ -254,6 +251,9 @@ final class RemotePrintSpooler { } 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(); @@ -262,23 +262,20 @@ final class RemotePrintSpooler { return false; } - public final void notifyClientForActivteJobs() { + public final void start() { throwIfCalledOnMainThread(); synchronized (mLock) { throwIfDestroyedLocked(); mCanUnbind = false; } - if (DEBUG) { - Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() - + "] notifyClientForActivteJobs()"); - } try { - getRemoteInstanceLazy().notifyClientForActivteJobs(); - } catch (RemoteException re) { - Slog.e(LOG_TAG, "Error asking for active print job notification.", re); + getRemoteInstanceLazy(); } catch (TimeoutException te) { - Slog.e(LOG_TAG, "Error asking for active print job notification.", te); + Slog.e(LOG_TAG, "Error starting the spooler.", te); } finally { + if (DEBUG) { + Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] start()"); + } synchronized (mLock) { mCanUnbind = true; mLock.notifyAll(); diff --git a/services/java/com/android/server/print/UserState.java b/services/java/com/android/server/print/UserState.java index c4fe124adbfee..00cc2ffca0e0e 100644 --- a/services/java/com/android/server/print/UserState.java +++ b/services/java/com/android/server/print/UserState.java @@ -166,7 +166,7 @@ final class UserState implements PrintSpoolerCallbacks { return mSpooler; } - public Map getActiveServices() { + public Map getActiveServicesLocked() { synchronized(mLock) { throwIfDestroyedLocked(); return mActiveServices;