Merge "Print job files and print job records not always cleaned up." into klp-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
b415525a16
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user