summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/print/IPrintSpooler.aidl1
-rw-r--r--core/java/android/print/IPrintSpoolerClient.aidl2
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java127
-rw-r--r--services/java/com/android/server/print/RemotePrintSpooler.java56
-rw-r--r--services/java/com/android/server/print/UserState.java180
5 files changed, 237 insertions, 129 deletions
diff --git a/core/java/android/print/IPrintSpooler.aidl b/core/java/android/print/IPrintSpooler.aidl
index 291e81f..96b168d 100644
--- a/core/java/android/print/IPrintSpooler.aidl
+++ b/core/java/android/print/IPrintSpooler.aidl
@@ -36,7 +36,6 @@ import android.print.PrintJobInfo;
*/
oneway interface IPrintSpooler {
void removeObsoletePrintJobs();
- void forgetPrintJobs(in List<PrintJobId> printJob);
void getPrintJobInfos(IPrintSpoolerCallbacks callback, in ComponentName componentName,
int state, int appId, int sequence);
void getPrintJobInfo(in PrintJobId printJobId, IPrintSpoolerCallbacks callback,
diff --git a/core/java/android/print/IPrintSpoolerClient.aidl b/core/java/android/print/IPrintSpoolerClient.aidl
index 0cf00cc..8270812 100644
--- a/core/java/android/print/IPrintSpoolerClient.aidl
+++ b/core/java/android/print/IPrintSpoolerClient.aidl
@@ -29,5 +29,5 @@ oneway interface IPrintSpoolerClient {
void onPrintJobQueued(in PrintJobInfo printJob);
void onAllPrintJobsForServiceHandled(in ComponentName printService);
void onAllPrintJobsHandled();
- void onPrintJobStateChanged(in PrintJobId printJobId, int appId);
+ void onPrintJobStateChanged(in PrintJobInfo printJob);
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
index 62b35fe..87181f7 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
@@ -43,6 +43,7 @@ import android.print.PrintManager;
import android.print.PrinterId;
import android.print.PrinterInfo;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.Log;
import android.util.Slog;
@@ -59,10 +60,12 @@ import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -82,6 +85,8 @@ public final class PrintSpoolerService extends Service {
private static final long CHECK_ALL_PRINTJOBS_HANDLED_DELAY = 5000;
+ private static final String PRINT_JOB_FILE_PREFIX = "print_job_";
+
private static final String PRINT_FILE_EXTENSION = "pdf";
private static final Object sLock = new Object();
@@ -168,9 +173,9 @@ public final class PrintSpoolerService extends Service {
PrintSpoolerService.this, 0, intent, PendingIntent.FLAG_ONE_SHOT
| PendingIntent.FLAG_CANCEL_CURRENT).getIntentSender();
- Message message = mHandlerCaller.obtainMessageIIO(
+ Message message = mHandlerCaller.obtainMessageO(
HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED,
- printJob.getAppId(), 0, printJob.getId());
+ printJob);
mHandlerCaller.executeOrSendMessage(message);
message = mHandlerCaller.obtainMessageOO(
@@ -179,9 +184,6 @@ public final class PrintSpoolerService extends Service {
mHandlerCaller.executeOrSendMessage(message);
printJob.setCreationTime(System.currentTimeMillis());
- synchronized (mLock) {
- mPersistanceManager.writeStateLocked();
- }
}
@Override
@@ -225,12 +227,40 @@ public final class PrintSpoolerService extends Service {
}
@Override
- public void forgetPrintJobs(List<PrintJobId> printJobIds) {
- PrintSpoolerService.this.forgetPrintJobs(printJobIds);
+ protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ PrintSpoolerService.this.dump(fd, writer, args);
}
};
}
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ synchronized (mLock) {
+ String prefix = args[0];
+ String tab = " ";
+
+ pw.append(prefix).append("print jobs:").println();
+ final int printJobCount = mPrintJobs.size();
+ for (int i = 0; i < printJobCount; i++) {
+ PrintJobInfo printJob = mPrintJobs.get(i);
+ pw.append(prefix).append(tab).append(printJob.toString());
+ pw.println();
+ }
+
+ pw.append(prefix).append("print job files:").println();
+ File[] files = getFilesDir().listFiles();
+ if (files != null) {
+ final int fileCount = files.length;
+ for (int i = 0; i < fileCount; i++) {
+ File file = files[i];
+ if (file.isFile() && file.getName().startsWith(PRINT_JOB_FILE_PREFIX)) {
+ pw.append(prefix).append(tab).append(file.getName()).println();
+ }
+ }
+ }
+ }
+ }
+
private void sendOnPrintJobQueued(PrintJobInfo printJob) {
Message message = mHandlerCaller.obtainMessageO(
HandlerCallerCallback.MSG_ON_PRINT_JOB_QUEUED, printJob);
@@ -324,10 +354,9 @@ public final class PrintSpoolerService extends Service {
case MSG_ON_PRINT_JOB_STATE_CHANGED: {
if (mClient != null) {
- PrintJobId printJobId = (PrintJobId) message.obj;
- final int appId = message.arg1;
+ PrintJobInfo printJob = (PrintJobInfo) message.obj;
try {
- mClient.onPrintJobStateChanged(printJobId, appId);
+ mClient.onPrintJobStateChanged(printJob);
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error notify for print job state change.", re);
}
@@ -391,17 +420,46 @@ public final class PrintSpoolerService extends Service {
public void createPrintJob(PrintJobInfo printJob) {
synchronized (mLock) {
addPrintJobLocked(printJob);
+ setPrintJobState(printJob.getId(), PrintJobInfo.STATE_CREATED, null);
}
}
private void handleReadPrintJobsLocked() {
+ // Make a map with the files for a print job since we may have
+ // to delete some. One example of getting orphan files if the
+ // spooler crashes while constructing a print job. We do not
+ // persist partially populated print jobs under construction to
+ // avoid special handling for various attributes missing.
+ ArrayMap<PrintJobId, File> fileForJobMap = null;
+ File[] files = getFilesDir().listFiles();
+ if (files != null) {
+ final int fileCount = files.length;
+ for (int i = 0; i < fileCount; i++) {
+ File file = files[i];
+ if (file.isFile() && file.getName().startsWith(PRINT_JOB_FILE_PREFIX)) {
+ if (fileForJobMap == null) {
+ fileForJobMap = new ArrayMap<PrintJobId, File>();
+ }
+ String printJobIdString = file.getName().substring(0,
+ PRINT_JOB_FILE_PREFIX.length());
+ PrintJobId printJobId = PrintJobId.unflattenFromString(
+ printJobIdString);
+ fileForJobMap.put(printJobId, file);
+ }
+ }
+ }
+
final int printJobCount = mPrintJobs.size();
for (int i = 0; i < printJobCount; i++) {
PrintJobInfo printJob = mPrintJobs.get(i);
+ // We want to have only the orphan files at the end.
+ if (fileForJobMap != null) {
+ fileForJobMap.remove(printJob.getId());
+ }
+
// Update the notification.
mNotificationController.onPrintJobStateChanged(printJob);
-
switch (printJob.getState()) {
case PrintJobInfo.STATE_QUEUED:
case PrintJobInfo.STATE_STARTED:
@@ -415,6 +473,15 @@ public final class PrintSpoolerService extends Service {
} break;
}
}
+
+ // Delete the orphan files.
+ if (fileForJobMap != null) {
+ final int orphanFileCount = fileForJobMap.size();
+ for (int i = 0; i < orphanFileCount; i++) {
+ File file = fileForJobMap.valueAt(i);
+ file.delete();
+ }
+ }
}
public void checkAllPrintJobsHandled() {
@@ -465,7 +532,7 @@ public final class PrintSpoolerService extends Service {
}
public File generateFileForPrintJob(PrintJobId printJobId) {
- return new File(getFilesDir(), "print_job_"
+ return new File(getFilesDir(), PRINT_JOB_FILE_PREFIX
+ printJobId.flattenToString() + "." + PRINT_FILE_EXTENSION);
}
@@ -476,31 +543,6 @@ public final class PrintSpoolerService extends Service {
}
}
- private void forgetPrintJobs(List<PrintJobId> printJobIds) {
- synchronized (mLock) {
- boolean printJobsRemoved = false;
- final int removedPrintJobCount = printJobIds.size();
- for (int i = 0; i < removedPrintJobCount; i++) {
- PrintJobId removedPrintJobId = printJobIds.get(i);
- final int printJobCount = mPrintJobs.size();
- for (int j = printJobCount - 1; j >= 0; j--) {
- PrintJobInfo printJob = mPrintJobs.get(j);
- if (removedPrintJobId.equals(printJob.getId())) {
- mPrintJobs.remove(j);
- printJobsRemoved = true;
- if (DEBUG_PRINT_JOB_LIFECYCLE) {
- Slog.i(LOG_TAG, "[FORGOT] " + printJob.getId().flattenToString());
- }
- removePrintJobFileLocked(printJob.getId());
- }
- }
- }
- if (printJobsRemoved) {
- mPersistanceManager.writeStateLocked();
- }
- }
- }
-
private void removeObsoletePrintJobs() {
synchronized (mLock) {
final int printJobCount = mPrintJobs.size();
@@ -523,7 +565,7 @@ public final class PrintSpoolerService extends Service {
if (file.exists()) {
file.delete();
if (DEBUG_PRINT_JOB_LIFECYCLE) {
- Slog.i(LOG_TAG, "[REMOVE FILE FOR] " + printJobId.flattenToString());
+ Slog.i(LOG_TAG, "[REMOVE FILE FOR] " + printJobId);
}
}
}
@@ -552,10 +594,7 @@ public final class PrintSpoolerService extends Service {
switch (state) {
case PrintJobInfo.STATE_COMPLETED:
case PrintJobInfo.STATE_CANCELED:
- // Just remove the file but keep the print job info since
- // the app that created it may be holding onto the PrintJob
- // instance and query it for its most recent state. We will
- // remove the info for this job when told so by the system.
+ mPrintJobs.remove(printJob);
removePrintJobFileLocked(printJob.getId());
// $fall-through$
@@ -582,9 +621,9 @@ public final class PrintSpoolerService extends Service {
notifyOnAllPrintJobsHandled();
}
- Message message = mHandlerCaller.obtainMessageIIO(
+ Message message = mHandlerCaller.obtainMessageO(
HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED,
- printJob.getAppId(), 0, printJob.getId());
+ printJob);
mHandlerCaller.executeOrSendMessage(message);
}
}
diff --git a/services/java/com/android/server/print/RemotePrintSpooler.java b/services/java/com/android/server/print/RemotePrintSpooler.java
index f98a805..798cea3 100644
--- a/services/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/java/com/android/server/print/RemotePrintSpooler.java
@@ -33,7 +33,6 @@ import android.print.IPrintSpoolerCallbacks;
import android.print.IPrintSpoolerClient;
import android.print.PrintJobId;
import android.print.PrintJobInfo;
-import android.print.PrintManager;
import android.util.Slog;
import android.util.TimedRemoteCaller;
@@ -91,7 +90,7 @@ final class RemotePrintSpooler {
public static interface PrintSpoolerCallbacks {
public void onPrintJobQueued(PrintJobInfo printJob);
public void onAllPrintJobsForServiceHandled(ComponentName printService);
- public void onPrintJobStateChanged(PrintJobId printJobId, int appId);
+ public void onPrintJobStateChanged(PrintJobInfo printJob);
}
public RemotePrintSpooler(Context context, int userId,
@@ -280,30 +279,6 @@ final class RemotePrintSpooler {
}
}
- public final void forgetPrintJobs(List<PrintJobId> printJobIds) {
- throwIfCalledOnMainThread();
- synchronized (mLock) {
- throwIfDestroyedLocked();
- mCanUnbind = false;
- }
- try {
- getRemoteInstanceLazy().forgetPrintJobs(printJobIds);
- } catch (RemoteException re) {
- Slog.e(LOG_TAG, "Error forgeting print jobs", re);
- } catch (TimeoutException te) {
- Slog.e(LOG_TAG, "Error forgeting print jobs", te);
- } finally {
- if (DEBUG) {
- Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
- + "] forgetPrintJobs()");
- }
- synchronized (mLock) {
- mCanUnbind = true;
- mLock.notifyAll();
- }
- }
- }
-
public final void destroy() {
throwIfCalledOnMainThread();
if (DEBUG) {
@@ -323,18 +298,15 @@ final class RemotePrintSpooler {
.append(String.valueOf(mDestroyed)).println();
pw.append(prefix).append("bound=")
.append((mRemoteInstance != null) ? "true" : "false").println();
- pw.append(prefix).append("print jobs:").println();
- if (mRemoteInstance != null) {
- List<PrintJobInfo> printJobs = getPrintJobInfos(null,
- PrintJobInfo.STATE_ANY, PrintManager.APP_ID_ANY);
- if (printJobs != null) {
- final int printJobCount = printJobs.size();
- for (int i = 0; i < printJobCount; i++) {
- PrintJobInfo printJob = printJobs.get(i);
- pw.append(prefix).append(prefix).append(printJob.toString());
- pw.println();
- }
- }
+
+ pw.flush();
+
+ try {
+ getRemoteInstanceLazy().asBinder().dump(fd, new String[]{prefix});
+ } catch (TimeoutException te) {
+ /* ignore */
+ } catch (RemoteException re) {
+ /* ignore */
}
}
}
@@ -346,8 +318,8 @@ final class RemotePrintSpooler {
}
}
- private void onPrintJobStateChanged(PrintJobId printJobId, int appId) {
- mCallbacks.onPrintJobStateChanged(printJobId, appId);
+ private void onPrintJobStateChanged(PrintJobInfo printJob) {
+ mCallbacks.onPrintJobStateChanged(printJob);
}
private IPrintSpooler getRemoteInstanceLazy() throws TimeoutException {
@@ -625,12 +597,12 @@ final class RemotePrintSpooler {
}
@Override
- public void onPrintJobStateChanged(PrintJobId printJobId, int appId) {
+ public void onPrintJobStateChanged(PrintJobInfo printJob) {
RemotePrintSpooler spooler = mWeakSpooler.get();
if (spooler != null) {
final long identity = Binder.clearCallingIdentity();
try {
- spooler.onPrintJobStateChanged(printJobId, appId);
+ spooler.onPrintJobStateChanged(printJob);
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/services/java/com/android/server/print/UserState.java b/services/java/com/android/server/print/UserState.java
index e5f5842..72acc53 100644
--- a/services/java/com/android/server/print/UserState.java
+++ b/services/java/com/android/server/print/UserState.java
@@ -33,7 +33,6 @@ import android.os.Looper;
import android.os.Message;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
-import android.os.UserManager;
import android.print.IPrintClient;
import android.print.IPrintDocumentAdapter;
import android.print.IPrintJobStateChangeListener;
@@ -52,6 +51,7 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
+import android.util.SparseArray;
import com.android.internal.R;
import com.android.internal.os.BackgroundThread;
@@ -62,6 +62,7 @@ import com.android.server.print.RemotePrintSpooler.PrintSpoolerCallbacks;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -93,8 +94,8 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
private final Set<ComponentName> mEnabledServices =
new ArraySet<ComponentName>();
- private final CreatedPrintJobTracker mCreatedPrintJobTracker =
- new CreatedPrintJobTracker();
+ private final PrintJobForAppCache mPrintJobForAppCache =
+ new PrintJobForAppCache();
private final Object mLock;
@@ -155,23 +156,22 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
public PrintJobInfo print(String printJobName, final IPrintClient client,
final IPrintDocumentAdapter documentAdapter, PrintAttributes attributes,
int appId) {
- PrintJobId printJobId = new PrintJobId();
-
- // Track this job so we can forget it when the creator dies.
- if (!mCreatedPrintJobTracker.onPrintJobCreatedLocked(client.asBinder(), printJobId)) {
- // Not adding a print job means the client is dead - done.
- return null;
- }
-
// Create print job place holder.
final PrintJobInfo printJob = new PrintJobInfo();
- printJob.setId(printJobId);
+ printJob.setId(new PrintJobId());
printJob.setAppId(appId);
printJob.setLabel(printJobName);
printJob.setAttributes(attributes);
printJob.setState(PrintJobInfo.STATE_CREATED);
printJob.setCopies(1);
+ // Track this job so we can forget it when the creator dies.
+ if (!mPrintJobForAppCache.onPrintJobCreated(client.asBinder(), appId,
+ printJob)) {
+ // Not adding a print job means the client is dead - done.
+ return null;
+ }
+
// Spin the spooler to add the job and show the config UI.
new AsyncTask<Void, Void, Void>() {
@Override
@@ -185,10 +185,40 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
}
public List<PrintJobInfo> getPrintJobInfos(int appId) {
- return mSpooler.getPrintJobInfos(null, PrintJobInfo.STATE_ANY, appId);
+ List<PrintJobInfo> cachedPrintJobs = mPrintJobForAppCache.getPrintJobs(appId);
+ // Note that the print spooler is not storing print jobs that
+ // are in a terminal state as it is non-trivial to properly update
+ // the spooler state for when to forget print jobs in terminal state.
+ // Therefore, we fuse the cached print jobs for running apps (some
+ // jobs are in a terminal state) with the ones that the print
+ // spooler knows about (some jobs are being processed).
+ ArrayMap<PrintJobId, PrintJobInfo> result =
+ new ArrayMap<PrintJobId, PrintJobInfo>();
+
+ // Add the cached print jobs for running apps.
+ final int cachedPrintJobCount = cachedPrintJobs.size();
+ for (int i = 0; i < cachedPrintJobCount; i++) {
+ PrintJobInfo cachedPrintJob = cachedPrintJobs.get(i);
+ result.put(cachedPrintJob.getId(), cachedPrintJob);
+ }
+
+ // Add everything else the spooler knows about.
+ List<PrintJobInfo> printJobs = mSpooler.getPrintJobInfos(null,
+ PrintJobInfo.STATE_ANY, appId);
+ final int printJobCount = printJobs.size();
+ for (int i = 0; i < printJobCount; i++) {
+ PrintJobInfo printJob = printJobs.get(i);
+ result.put(printJob.getId(), printJob);
+ }
+
+ return new ArrayList<PrintJobInfo>(result.values());
}
public PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId) {
+ PrintJobInfo printJob = mPrintJobForAppCache.getPrintJob(printJobId, appId);
+ if (printJob != null) {
+ return printJob;
+ }
return mSpooler.getPrintJobInfo(printJobId, appId);
}
@@ -398,9 +428,10 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
}
@Override
- public void onPrintJobStateChanged(PrintJobId printJobId, int appId) {
+ public void onPrintJobStateChanged(PrintJobInfo printJob) {
+ mPrintJobForAppCache.onPrintJobStateChanged(printJob);
mHandler.obtainMessage(UserStateHandler.MSG_DISPATCH_PRINT_JOB_STATE_CHANGED,
- appId, 0, printJobId).sendToTarget();
+ printJob.getAppId(), 0, printJob.getId()).sendToTarget();
}
@Override
@@ -525,6 +556,9 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
pw.println();
}
+ pw.append(prefix).append(tab).append("cached print jobs:").println();
+ mPrintJobForAppCache.dump(pw, prefix + tab + tab);
+
pw.append(prefix).append(tab).append("discovery mediator:").println();
if (mPrinterDiscoverySession != null) {
mPrinterDiscoverySession.dump(pw, prefix + tab + tab);
@@ -1424,34 +1458,19 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
}
}
- private final class CreatedPrintJobTracker {
- private final ArrayMap<IBinder, List<PrintJobId>> mCreatedPrintJobs =
- new ArrayMap<IBinder, List<PrintJobId>>();
+ private final class PrintJobForAppCache {
+ private final SparseArray<List<PrintJobInfo>> mPrintJobsForRunningApp =
+ new SparseArray<List<PrintJobInfo>>();
- public boolean onPrintJobCreatedLocked(final IBinder creator, PrintJobId printJobId) {
+ public boolean onPrintJobCreated(final IBinder creator, final int appId,
+ PrintJobInfo printJob) {
try {
creator.linkToDeath(new DeathRecipient() {
@Override
public void binderDied() {
creator.unlinkToDeath(this, 0);
- UserManager userManager = (UserManager) mContext.getSystemService(
- Context.USER_SERVICE);
- // If the death is a result of the user being removed, then
- // do nothing since the spooler data for this user will be
- // wiped and we cannot bind to the spooler at this point.
- if (userManager.getUserInfo(mUserId) == null) {
- return;
- }
- List<PrintJobId> printJobIds = null;
synchronized (mLock) {
- printJobIds = mCreatedPrintJobs.remove(creator);
- if (printJobIds == null) {
- return;
- }
- printJobIds = new ArrayList<PrintJobId>(printJobIds);
- }
- if (printJobIds != null) {
- mSpooler.forgetPrintJobs(printJobIds);
+ mPrintJobsForRunningApp.remove(appId);
}
}
}, 0);
@@ -1460,14 +1479,93 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
return false;
}
synchronized (mLock) {
- List<PrintJobId> printJobIds = mCreatedPrintJobs.get(creator);
- if (printJobIds == null) {
- printJobIds = new ArrayList<PrintJobId>();
- mCreatedPrintJobs.put(creator, printJobIds);
+ List<PrintJobInfo> printJobsForApp = mPrintJobsForRunningApp.get(appId);
+ if (printJobsForApp == null) {
+ printJobsForApp = new ArrayList<PrintJobInfo>();
+ mPrintJobsForRunningApp.put(appId, printJobsForApp);
}
- printJobIds.add(printJobId);
+ printJobsForApp.add(printJob);
}
return true;
}
+
+ public void onPrintJobStateChanged(PrintJobInfo printJob) {
+ synchronized (mLock) {
+ List<PrintJobInfo> printJobsForApp = mPrintJobsForRunningApp.get(
+ printJob.getAppId());
+ if (printJobsForApp == null) {
+ return;
+ }
+ final int printJobCount = printJobsForApp.size();
+ for (int i = 0; i < printJobCount; i++) {
+ PrintJobInfo oldPrintJob = printJobsForApp.get(i);
+ if (oldPrintJob.getId().equals(printJob.getId())) {
+ printJobsForApp.set(i, printJob);
+ }
+ }
+ }
+ }
+
+ public PrintJobInfo getPrintJob(PrintJobId printJobId, int appId) {
+ synchronized (mLock) {
+ List<PrintJobInfo> printJobsForApp = mPrintJobsForRunningApp.get(appId);
+ if (printJobsForApp == null) {
+ return null;
+ }
+ final int printJobCount = printJobsForApp.size();
+ for (int i = 0; i < printJobCount; i++) {
+ PrintJobInfo printJob = printJobsForApp.get(i);
+ if (printJob.getId().equals(printJobId)) {
+ return printJob;
+ }
+ }
+ }
+ return null;
+ }
+
+ public List<PrintJobInfo> getPrintJobs(int appId) {
+ synchronized (mLock) {
+ List<PrintJobInfo> printJobs = null;
+ if (appId == PrintManager.APP_ID_ANY) {
+ final int bucketCount = mPrintJobsForRunningApp.size();
+ for (int i = 0; i < bucketCount; i++) {
+ List<PrintJobInfo> bucket = mPrintJobsForRunningApp.valueAt(i);
+ if (printJobs == null) {
+ printJobs = new ArrayList<PrintJobInfo>();
+ }
+ printJobs.addAll(bucket);
+ }
+ } else {
+ List<PrintJobInfo> bucket = mPrintJobsForRunningApp.get(appId);
+ if (bucket != null) {
+ if (printJobs == null) {
+ printJobs = new ArrayList<PrintJobInfo>();
+ }
+ printJobs.addAll(bucket);
+ }
+ }
+ if (printJobs != null) {
+ return printJobs;
+ }
+ return Collections.emptyList();
+ }
+ }
+
+ public void dump(PrintWriter pw, String prefix) {
+ synchronized (mLock) {
+ String tab = " ";
+ final int bucketCount = mPrintJobsForRunningApp.size();
+ for (int i = 0; i < bucketCount; i++) {
+ final int appId = mPrintJobsForRunningApp.keyAt(i);
+ pw.append(prefix).append("appId=" + appId).append(':').println();
+ List<PrintJobInfo> bucket = mPrintJobsForRunningApp.valueAt(i);
+ final int printJobCount = bucket.size();
+ for (int j = 0; j < printJobCount; j++) {
+ PrintJobInfo printJob = bucket.get(j);
+ pw.append(prefix).append(tab).append(printJob.toString()).println();
+ }
+ }
+ }
+ }
}
}