Merge "App UI freezes when printing. API clean up." into klp-dev

This commit is contained in:
Svetoslav
2013-09-17 02:28:34 +00:00
committed by Android (Google) Code Review
24 changed files with 621 additions and 403 deletions

View File

@@ -19174,15 +19174,21 @@ package android.print {
public final class PrintJob {
method public void cancel();
method public int getId();
method public android.print.PrintJobId getId();
method public android.print.PrintJobInfo getInfo();
}
public final class PrintJobId implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
}
public final class PrintJobInfo implements android.os.Parcelable {
method public int describeContents();
method public android.print.PrintAttributes getAttributes();
method public int getCopies();
method public int getId();
method public android.print.PrintJobId getId();
method public java.lang.String getLabel();
method public android.print.PageRange[] getPages();
method public android.print.PrinterId getPrinterId();
@@ -19194,6 +19200,7 @@ package android.print {
field public static final int STATE_BLOCKED = 4; // 0x4
field public static final int STATE_CANCELED = 7; // 0x7
field public static final int STATE_COMPLETED = 5; // 0x5
field public static final int STATE_CREATED = 1; // 0x1
field public static final int STATE_FAILED = 6; // 0x6
field public static final int STATE_QUEUED = 2; // 0x2
field public static final int STATE_STARTED = 3; // 0x3
@@ -19201,7 +19208,6 @@ package android.print {
public final class PrintManager {
method public java.util.List<android.print.PrintJob> getPrintJobs();
method public android.print.PrintJob print(java.lang.String, java.io.File, android.print.PrintDocumentInfo, android.print.PrintAttributes);
method public android.print.PrintJob print(java.lang.String, android.print.PrintDocumentAdapter, android.print.PrintAttributes);
}
@@ -19312,7 +19318,7 @@ package android.printservice {
method public boolean complete();
method public boolean fail(java.lang.String);
method public android.printservice.PrintDocument getDocument();
method public int getId();
method public android.print.PrintJobId getId();
method public android.print.PrintJobInfo getInfo();
method public boolean isBlocked();
method public boolean isCancelled();

View File

@@ -19,6 +19,7 @@ package android.print;
import android.print.IPrinterDiscoveryObserver;
import android.print.IPrintDocumentAdapter;
import android.print.IPrintClient;
import android.print.PrintJobId;
import android.print.PrinterId;
import android.print.PrintJobInfo;
import android.print.PrintAttributes;
@@ -31,12 +32,12 @@ import android.printservice.PrintServiceInfo;
*/
interface IPrintManager {
List<PrintJobInfo> getPrintJobInfos(int appId, int userId);
PrintJobInfo getPrintJobInfo(int printJobId, int appId, int userId);
PrintJobInfo getPrintJobInfo(in PrintJobId printJobId, int appId, int userId);
PrintJobInfo print(String printJobName, in IPrintClient client,
in IPrintDocumentAdapter printAdapter, in PrintAttributes attributes,
int appId, int userId);
void cancelPrintJob(int printJobId, int appId, int userId);
void restartPrintJob(int printJobId, int appId, int userId);
void cancelPrintJob(in PrintJobId printJobId, int appId, int userId);
void restartPrintJob(in PrintJobId printJobId, int appId, int userId);
List<PrintServiceInfo> getEnabledPrintServices(int userId);

View File

@@ -24,6 +24,8 @@ import android.print.IPrintSpoolerClient;
import android.print.IPrintSpoolerCallbacks;
import android.print.PrinterInfo;
import android.print.PrintAttributes;
import android.print.PrintJobId;
import android.print.PrintJobInfo;
/**
* Interface for communication with the print spooler service.
@@ -33,17 +35,18 @@ import android.print.PrintAttributes;
* @hide
*/
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(int printJobId, IPrintSpoolerCallbacks callback,
void getPrintJobInfo(in PrintJobId printJobId, IPrintSpoolerCallbacks callback,
int appId, int sequence);
void createPrintJob(String printJobName, in IPrintClient client,
in IPrintDocumentAdapter printAdapter, in PrintAttributes attributes,
IPrintSpoolerCallbacks callback, int appId, int sequence);
void setPrintJobState(int printJobId, int status, String error,
void createPrintJob(in PrintJobInfo printJob, in IPrintClient client,
in IPrintDocumentAdapter printAdapter);
void setPrintJobState(in PrintJobId printJobId, int status, String stateReason,
IPrintSpoolerCallbacks callback, int sequence);
void setPrintJobTag(int printJobId, String tag, IPrintSpoolerCallbacks callback,
void setPrintJobTag(in PrintJobId printJobId, String tag, IPrintSpoolerCallbacks callback,
int sequence);
void writePrintJobData(in ParcelFileDescriptor fd, int printJobId);
void writePrintJobData(in ParcelFileDescriptor fd, in PrintJobId printJobId);
void setClient(IPrintSpoolerClient client);
}

View File

@@ -28,7 +28,6 @@ import java.util.List;
*/
oneway interface IPrintSpoolerCallbacks {
void onGetPrintJobInfosResult(in List<PrintJobInfo> printJob, int sequence);
void onCreatePrintJobResult(in PrintJobInfo printJob, int sequence);
void onCancelPrintJobResult(boolean canceled, int sequence);
void onSetPrintJobStateResult(boolean success, int sequence);
void onSetPrintJobTagResult(boolean success, int sequence);

View File

@@ -18,6 +18,7 @@ package android.print;
import android.print.PrinterId;
import android.print.PrinterInfo;
import android.content.pm.ParceledListSlice;
/**
* Interface for observing discovered printers by a discovery session.
@@ -25,6 +26,6 @@ import android.print.PrinterInfo;
* @hide
*/
oneway interface IPrinterDiscoveryObserver {
void onPrintersAdded(in List<PrinterInfo> printers);
void onPrintersRemoved(in List<PrinterId> printerIds);
void onPrintersAdded(in ParceledListSlice printers);
void onPrintersRemoved(in ParceledListSlice printerIds);
}

View File

@@ -22,8 +22,6 @@ package android.print;
*/
public final class PrintJob {
private final int mId;
private final PrintManager mPrintManager;
private PrintJobInfo mCachedInfo;
@@ -31,7 +29,6 @@ public final class PrintJob {
PrintJob(PrintJobInfo info, PrintManager printManager) {
mCachedInfo = info;
mPrintManager = printManager;
mId = info.getId();
}
/**
@@ -39,8 +36,8 @@ public final class PrintJob {
*
* @return The id.
*/
public int getId() {
return mId;
public PrintJobId getId() {
return mCachedInfo.getId();
}
/**
@@ -57,7 +54,7 @@ public final class PrintJob {
if (isInImmutableState()) {
return mCachedInfo;
}
PrintJobInfo info = mPrintManager.getPrintJobInfo(mId);
PrintJobInfo info = mPrintManager.getPrintJobInfo(mCachedInfo.getId());
if (info != null) {
mCachedInfo = info;
}
@@ -69,7 +66,7 @@ public final class PrintJob {
*/
public void cancel() {
if (!isInImmutableState()) {
mPrintManager.cancelPrintJob(mId);
mPrintManager.cancelPrintJob(mCachedInfo.getId());
}
}
@@ -91,11 +88,11 @@ public final class PrintJob {
return false;
}
PrintJob other = (PrintJob) obj;
return mId == other.mId;
return mCachedInfo.getId().equals(other.mCachedInfo.getId());
}
@Override
public int hashCode() {
return mId;
return mCachedInfo.getId().hashCode();
}
}

View File

@@ -0,0 +1,19 @@
/**
* Copyright (c) 2013, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.print;
parcelable PrintJobId;

View File

@@ -0,0 +1,122 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.print;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import java.util.UUID;
/**
* This class represents the id of a print job.
*/
public final class PrintJobId implements Parcelable {
private final String mValue;
/**
* Creates a new instance.
*
* @hide
*/
public PrintJobId() {
this(UUID.randomUUID().toString());
}
/**
* Creates a new instance.
*
* @param value The internal value.
*
* @hide
*/
public PrintJobId(String value) {
mValue = value;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((mValue != null) ? mValue.hashCode() : 0);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
PrintJobId other = (PrintJobId) obj;
if (!TextUtils.equals(mValue, other.mValue)) {
return false;
}
return true;
}
@Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeString(mValue);
}
@Override
public int describeContents() {
return 0;
}
/**
* Flattens this id to a string.
*
* @return The flattened id.
*
* @hide
*/
public String flattenToString() {
return mValue;
}
/**
* Unflattens a print job id from a string.
*
* @string The string.
* @return The unflattened id, or null if the string is malformed.
*
* @hide
*/
public static PrintJobId unflattenFromString(String string) {
return new PrintJobId(string);
}
public static final Parcelable.Creator<PrintJobId> CREATOR =
new Parcelable.Creator<PrintJobId>() {
@Override
public PrintJobId createFromParcel(Parcel parcel) {
return new PrintJobId(parcel.readString());
}
@Override
public PrintJobId[] newArray(int size) {
return new PrintJobId[size];
}
};
}

View File

@@ -56,8 +56,6 @@ public final class PrintJobInfo implements Parcelable {
* <p>
* Next valid states: {@link #STATE_QUEUED}
* </p>
*
* @hide
*/
public static final int STATE_CREATED = 1;
@@ -117,7 +115,7 @@ public final class PrintJobInfo implements Parcelable {
public static final int STATE_CANCELED = 7;
/** The unique print job id. */
private int mId;
private PrintJobId mId;
/** The human readable print job label. */
private String mLabel;
@@ -178,7 +176,7 @@ public final class PrintJobInfo implements Parcelable {
}
private PrintJobInfo(Parcel parcel) {
mId = parcel.readInt();
mId = parcel.readParcelable(null);
mLabel = parcel.readString();
mPrinterId = parcel.readParcelable(null);
mPrinterName = parcel.readString();
@@ -208,7 +206,7 @@ public final class PrintJobInfo implements Parcelable {
*
* @return The id.
*/
public int getId() {
public PrintJobId getId() {
return mId;
}
@@ -219,7 +217,7 @@ public final class PrintJobInfo implements Parcelable {
*
* @hide
*/
public void setId(int id) {
public void setId(PrintJobId id) {
this.mId = id;
}
@@ -485,7 +483,7 @@ public final class PrintJobInfo implements Parcelable {
@Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(mId);
parcel.writeParcelable(mId, flags);
parcel.writeString(mLabel);
parcel.writeParcelable(mPrinterId, flags);
parcel.writeString(mPrinterName);

View File

@@ -36,7 +36,6 @@ import com.android.internal.os.SomeArgs;
import libcore.io.IoUtils;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
@@ -114,7 +113,7 @@ public final class PrintManager {
return new PrintManager(mContext, mService, userId, APP_ID_ANY);
}
PrintJobInfo getPrintJobInfo(int printJobId) {
PrintJobInfo getPrintJobInfo(PrintJobId printJobId) {
try {
return mService.getPrintJobInfo(printJobId, mAppId, mUserId);
} catch (RemoteException re) {
@@ -148,7 +147,7 @@ public final class PrintManager {
return Collections.emptyList();
}
void cancelPrintJob(int printJobId) {
void cancelPrintJob(PrintJobId printJobId) {
try {
mService.cancelPrintJob(printJobId, mAppId, mUserId);
} catch (RemoteException re) {
@@ -156,24 +155,6 @@ public final class PrintManager {
}
}
/**
* Creates a print job for printing a file with default print attributes.
*
* @param printJobName A name for the new print job.
* @param pdfFile The PDF file to print.
* @param documentInfo Information about the printed document.
* @param attributes The default print job attributes.
* @return The created print job on success or null on failure.
*
* @see PrintJob
*/
public PrintJob print(String printJobName, File pdfFile, PrintDocumentInfo documentInfo,
PrintAttributes attributes) {
PrintFileDocumentAdapter documentAdapter = new PrintFileDocumentAdapter(
mContext, pdfFile, documentInfo);
return print(printJobName, documentAdapter, attributes);
}
/**
* Creates a print job for printing a {@link PrintDocumentAdapter} with default print
* attributes.

View File

@@ -17,6 +17,7 @@
package android.print;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -270,20 +271,22 @@ public final class PrinterDiscoverySession {
}
@Override
public void onPrintersAdded(List<PrinterInfo> printers) {
@SuppressWarnings("rawtypes")
public void onPrintersAdded(ParceledListSlice printers) {
PrinterDiscoverySession session = mWeakSession.get();
if (session != null) {
session.mHandler.obtainMessage(MSG_PRINTERS_ADDED,
printers).sendToTarget();
printers.getList()).sendToTarget();
}
}
@Override
public void onPrintersRemoved(List<PrinterId> printerIds) {
@SuppressWarnings("rawtypes")
public void onPrintersRemoved(ParceledListSlice printerIds) {
PrinterDiscoverySession session = mWeakSession.get();
if (session != null) {
session.mHandler.obtainMessage(MSG_PRINTERS_REMOVED,
printerIds).sendToTarget();
printerIds.getList()).sendToTarget();
}
}
}

View File

@@ -20,6 +20,8 @@ import android.os.ParcelFileDescriptor;
import android.print.PrintJobInfo;
import android.print.PrinterId;
import android.print.PrinterInfo;
import android.print.PrintJobId;
import android.content.pm.ParceledListSlice;
/**
* The top-level interface from a print service to the system.
@@ -28,11 +30,11 @@ import android.print.PrinterInfo;
*/
interface IPrintServiceClient {
List<PrintJobInfo> getPrintJobInfos();
PrintJobInfo getPrintJobInfo(int printJobId);
boolean setPrintJobState(int printJobId, int state, String error);
boolean setPrintJobTag(int printJobId, String tag);
oneway void writePrintJobData(in ParcelFileDescriptor fd, int printJobId);
PrintJobInfo getPrintJobInfo(in PrintJobId printJobId);
boolean setPrintJobState(in PrintJobId printJobId, int state, String error);
boolean setPrintJobTag(in PrintJobId printJobId, String tag);
oneway void writePrintJobData(in ParcelFileDescriptor fd, in PrintJobId printJobId);
void onPrintersAdded(in List<PrinterInfo> printers);
void onPrintersRemoved(in List<PrinterId> printerIds);
void onPrintersAdded(in ParceledListSlice printers);
void onPrintersRemoved(in ParceledListSlice printerIds);
}

View File

@@ -19,6 +19,7 @@ package android.printservice;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.print.PrintDocumentInfo;
import android.print.PrintJobId;
import android.util.Log;
import java.io.IOException;
@@ -35,13 +36,13 @@ public final class PrintDocument {
private static final String LOG_TAG = "PrintDocument";
private final int mPrintJobId;
private final PrintJobId mPrintJobId;
private final IPrintServiceClient mPrintServiceClient;
private final PrintDocumentInfo mInfo;
PrintDocument(int printJobId, IPrintServiceClient printServiceClient,
PrintDocument(PrintJobId printJobId, IPrintServiceClient printServiceClient,
PrintDocumentInfo info) {
mPrintJobId = printJobId;
mPrintServiceClient = printServiceClient;

View File

@@ -17,6 +17,7 @@
package android.printservice;
import android.os.RemoteException;
import android.print.PrintJobId;
import android.print.PrintJobInfo;
import android.text.TextUtils;
import android.util.Log;
@@ -52,7 +53,7 @@ public final class PrintJob {
*
* @return The id.
*/
public int getId() {
public PrintJobId getId() {
PrintService.throwIfNotCalledOnMainThread();
return mCachedInfo.getId();
}
@@ -312,12 +313,12 @@ public final class PrintJob {
return false;
}
PrintJob other = (PrintJob) obj;
return (mCachedInfo.getId() == other.mCachedInfo.getId());
return (mCachedInfo.getId().equals(other.mCachedInfo.getId()));
}
@Override
public int hashCode() {
return mCachedInfo.getId();
return mCachedInfo.getId().hashCode();
}
private boolean isInImmutableState() {

View File

@@ -16,6 +16,7 @@
package android.printservice;
import android.content.pm.ParceledListSlice;
import android.os.RemoteException;
import android.print.PrinterCapabilitiesInfo;
import android.print.PrinterId;
@@ -80,8 +81,6 @@ import java.util.List;
public abstract class PrinterDiscoverySession {
private static final String LOG_TAG = "PrinterDiscoverySession";
private static final int MAX_ITEMS_PER_CALLBACK = 50;
private static int sIdCounter = 0;
private final int mId;
@@ -112,7 +111,11 @@ public abstract class PrinterDiscoverySession {
// If some printers were added in the method that
// created the session, send them over.
if (!mPrinters.isEmpty()) {
sendAddedPrinters(mObserver, getPrinters());
try {
mObserver.onPrintersAdded(new ParceledListSlice<PrinterInfo>(getPrinters()));
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error sending added printers", re);
}
}
}
@@ -184,7 +187,11 @@ public abstract class PrinterDiscoverySession {
// Send the added printers, if such.
if (addedPrinters != null) {
sendAddedPrinters(mObserver, addedPrinters);
try {
mObserver.onPrintersAdded(new ParceledListSlice<PrinterInfo>(addedPrinters));
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error sending added printers", re);
}
}
} else {
// Remember the last sent printers if needed.
@@ -203,27 +210,6 @@ public abstract class PrinterDiscoverySession {
}
}
private static void sendAddedPrinters(IPrintServiceClient observer,
List<PrinterInfo> printers) {
try {
final int printerCount = printers.size();
if (printerCount <= MAX_ITEMS_PER_CALLBACK) {
observer.onPrintersAdded(printers);
} else {
// Send the added printers in chunks avoiding the binder transaction limit.
final int transactionCount = (printerCount / MAX_ITEMS_PER_CALLBACK) + 1;
for (int i = 0; i < transactionCount; i++) {
final int start = i * MAX_ITEMS_PER_CALLBACK;
final int end = Math.min(start + MAX_ITEMS_PER_CALLBACK, printerCount);
List<PrinterInfo> subPrinters = printers.subList(start, end);
observer.onPrintersAdded(subPrinters);
}
}
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error sending added printers", re);
}
}
/**
* Removes added printers. Removing an already removed or never added
* printer has no effect. Removed printers can be added again. You can
@@ -261,7 +247,12 @@ public abstract class PrinterDiscoverySession {
// Send the removed printers, if such.
if (!removedPrinterIds.isEmpty()) {
sendRemovedPrinters(mObserver, removedPrinterIds);
try {
mObserver.onPrintersRemoved(new ParceledListSlice<PrinterId>(
removedPrinterIds));
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error sending removed printers", re);
}
}
} else {
// Remember the last sent printers if needed.
@@ -278,26 +269,6 @@ public abstract class PrinterDiscoverySession {
}
}
private static void sendRemovedPrinters(IPrintServiceClient observer,
List<PrinterId> printerIds) {
try {
final int printerIdCount = printerIds.size();
if (printerIdCount <= MAX_ITEMS_PER_CALLBACK) {
observer.onPrintersRemoved(printerIds);
} else {
final int transactionCount = (printerIdCount / MAX_ITEMS_PER_CALLBACK) + 1;
for (int i = 0; i < transactionCount; i++) {
final int start = i * MAX_ITEMS_PER_CALLBACK;
final int end = Math.min(start + MAX_ITEMS_PER_CALLBACK, printerIdCount);
List<PrinterId> subPrinterIds = printerIds.subList(start, end);
observer.onPrintersRemoved(subPrinterIds);
}
}
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error sending removed printers", re);
}
}
private void sendOutOfDiscoveryPeriodPrinterChanges() {
// Noting changed since the last discovery period - nothing to do.
if (mLastSentPrinters == null || mLastSentPrinters.isEmpty()) {
@@ -319,7 +290,11 @@ public abstract class PrinterDiscoverySession {
// Send the added printers, if such.
if (addedPrinters != null) {
sendAddedPrinters(mObserver, addedPrinters);
try {
mObserver.onPrintersAdded(new ParceledListSlice<PrinterInfo>(addedPrinters));
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error sending added printers", re);
}
}
// Determine the removed printers.
@@ -335,7 +310,11 @@ public abstract class PrinterDiscoverySession {
// Send the removed printers, if such.
if (removedPrinterIds != null) {
sendRemovedPrinters(mObserver, removedPrinterIds);
try {
mObserver.onPrintersRemoved(new ParceledListSlice<PrinterId>(removedPrinterIds));
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error sending removed printers", re);
}
}
mLastSentPrinters = null;

View File

@@ -44,7 +44,7 @@
<uses-sdk android:minSdkVersion="18" android:targetSdkVersion="18"/>
<application
android:allowClearUserData="false"
android:allowClearUserData="true"
android:label="@string/app_label"
android:allowBackup= "false"
android:supportsRtl="true">

View File

@@ -139,18 +139,20 @@
<!-- Title of an application permission, listed so the user can choose whether they want
to allow the application to do this. -->
<string name="permlab_accessAllPrintJobs">access all print jobs</string>
<string name="permlab_accessAllPrintJobs" translatable="false">access all print jobs</string>
<!-- Description of an application permission, listed so the user can choose whether
they want to allow the application to do this. -->
<string name="permdesc_accessAllPrintJobs">Allows the holder to access print jobs
created by another app. Should never be needed for normal apps.</string>
<string name="permdesc_accessAllPrintJobs" translatable="false">Allows the holder to access
print jobs created by another app. Should never be needed for normal apps.</string>
<!-- Title of an application permission, listed so the user can choose whether they want
to allow the application to do this. -->
<string name="permlab_startPrintServiceConfigActivity">start print service configuration activities</string>
<string name="permlab_startPrintServiceConfigActivity" translatable="false">start print
service configuration activities</string>
<!-- Description of an application permission, listed so the user can choose whether they
want to allow the application to do this. -->
<string name="permdesc_startPrintServiceConfigActivity">Allows the holder to start the
configuration activities of a print service. Should never be needed for normal apps.</string>
<string name="permdesc_startPrintServiceConfigActivity" translatable="false">Allows the
holder to start the configuration activities of a print service. Should never be needed
for normal apps.</string>
</resources>

View File

@@ -23,13 +23,13 @@ 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;
import android.print.IPrintManager;
import android.print.PrintJobId;
import android.print.PrintJobInfo;
import android.print.PrintManager;
import android.text.TextUtils;
@@ -40,12 +40,13 @@ import android.util.Log;
* based on print job state transitions.
*/
public class NotificationController {
public static final boolean DEBUG = true && Build.IS_DEBUGGABLE;
public static final boolean DEBUG = false;
public static final String LOG_TAG = "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";
@@ -61,8 +62,9 @@ public class NotificationController {
public void onPrintJobStateChanged(PrintJobInfo printJob) {
if (DEBUG) {
Log.i(LOG_TAG, "onPrintJobStateChanged() printJobId: " + printJob.getId()
+ " state:" + PrintJobInfo.stateToString(printJob.getState()));
Log.i(LOG_TAG, "onPrintJobStateChanged() printJobId: "
+ printJob.getId().flattenToString() + " state:"
+ PrintJobInfo.stateToString(printJob.getState()));
}
switch (printJob.getState()) {
case PrintJobInfo.STATE_QUEUED:
@@ -96,7 +98,7 @@ public class NotificationController {
.setWhen(System.currentTimeMillis())
.setOngoing(true)
.setShowWhen(true);
mNotificationManager.notify(printJob.getId(), builder.build());
mNotificationManager.notify(printJob.getId().flattenToString(), 0, builder.build());
}
private void createFailedNotification(PrintJobInfo printJob) {
@@ -115,7 +117,7 @@ public class NotificationController {
.setWhen(System.currentTimeMillis())
.setOngoing(true)
.setShowWhen(true);
mNotificationManager.notify(printJob.getId(), builder.build());
mNotificationManager.notify(printJob.getId().flattenToString(), 0, builder.build());
}
private void createBlockedNotification(PrintJobInfo printJob) {
@@ -132,25 +134,25 @@ public class NotificationController {
.setWhen(System.currentTimeMillis())
.setOngoing(true)
.setShowWhen(true);
mNotificationManager.notify(printJob.getId(), builder.build());
mNotificationManager.notify(printJob.getId().flattenToString(), 0, builder.build());
}
private void removeNotification(int printJobId) {
mNotificationManager.cancel(printJobId);
private void removeNotification(PrintJobId printJobId) {
mNotificationManager.cancel(printJobId.flattenToString(), 0);
}
private PendingIntent createCancelIntent(PrintJobInfo printJob) {
Intent intent = new Intent(mContext, NotificationBroadcastReceiver.class);
intent.setAction(INTENT_ACTION_CANCEL_PRINTJOB + "_" + String.valueOf(printJob.getId()));
intent.setAction(INTENT_ACTION_CANCEL_PRINTJOB + "_" + printJob.getId().flattenToString());
intent.putExtra(INTENT_EXTRA_PRINTJOB_ID, printJob.getId());
intent.putExtra(INTENT_EXTRA_PRINTJOB_LABEL, printJob.getLabel());
intent.putExtra(INTENT_EXTRA_PRINTER_NAME, printJob.getPrinterName());
return PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT);
}
private PendingIntent createRestartIntent(int printJobId) {
private PendingIntent createRestartIntent(PrintJobId printJobId) {
Intent intent = new Intent(mContext, NotificationBroadcastReceiver.class);
intent.setAction(INTENT_ACTION_RESTART_PRINTJOB + "_" + String.valueOf(printJobId));
intent.setAction(INTENT_ACTION_RESTART_PRINTJOB + "_" + printJobId.flattenToString());
intent.putExtra(INTENT_EXTRA_PRINTJOB_ID, printJobId);
return PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT);
}
@@ -162,17 +164,17 @@ public class NotificationController {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action != null && action.startsWith(INTENT_ACTION_CANCEL_PRINTJOB)) {
final int printJobId = intent.getExtras().getInt(INTENT_EXTRA_PRINTJOB_ID);
PrintJobId printJobId = intent.getExtras().getParcelable(INTENT_EXTRA_PRINTJOB_ID);
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);
PrintJobId printJobId = intent.getExtras().getParcelable(INTENT_EXTRA_PRINTJOB_ID);
handleRestartPrintJob(context, printJobId);
}
}
private void handleCancelPrintJob(final Context context, final int printJobId,
private void handleCancelPrintJob(final Context context, final PrintJobId printJobId,
final String printJobLabel, final String printerName) {
if (DEBUG) {
Log.i(LOG_TAG, "handleCancelPrintJob() printJobId:" + printJobId);
@@ -190,7 +192,7 @@ public class NotificationController {
.setWhen(System.currentTimeMillis())
.setOngoing(true)
.setShowWhen(true);
notificationManager.notify(printJobId, builder.build());
notificationManager.notify(printJobId.flattenToString(), 0, 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
@@ -226,7 +228,7 @@ public class NotificationController {
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
}
private void handleRestartPrintJob(final Context context, final int printJobId) {
private void handleRestartPrintJob(final Context context, final PrintJobId printJobId) {
if (DEBUG) {
Log.i(LOG_TAG, "handleRestartPrintJob() printJobId:" + printJobId);
}

View File

@@ -47,6 +47,7 @@ import android.print.PrintAttributes.MediaSize;
import android.print.PrintAttributes.Resolution;
import android.print.PrintDocumentAdapter;
import android.print.PrintDocumentInfo;
import android.print.PrintJobId;
import android.print.PrintJobInfo;
import android.print.PrintManager;
import android.print.PrinterCapabilitiesInfo;
@@ -104,8 +105,7 @@ public class PrintJobConfigActivity extends Activity {
private static final boolean DEBUG = true && Build.IS_DEBUGGABLE;
public static final String EXTRA_PRINT_DOCUMENT_ADAPTER = "printDocumentAdapter";
public static final String EXTRA_PRINT_ATTRIBUTES = "printAttributes";
public static final String EXTRA_PRINT_JOB_ID = "printJobId";
public static final String EXTRA_PRINT_JOB = "printJob";
public static final String INTENT_EXTRA_PRINTER_ID = "INTENT_EXTRA_PRINTER_ID";
@@ -163,7 +163,7 @@ public class PrintJobConfigActivity extends Activity {
private Document mDocument;
private PrintController mController;
private int mPrintJobId;
private PrintJobId mPrintJobId;
private IBinder mIPrintDocumentAdapter;
@@ -175,17 +175,18 @@ public class PrintJobConfigActivity extends Activity {
Bundle extras = getIntent().getExtras();
mPrintJobId = extras.getInt(EXTRA_PRINT_JOB_ID, -1);
if (mPrintJobId < 0) {
throw new IllegalArgumentException("Invalid print job id: " + mPrintJobId);
PrintJobInfo printJob = extras.getParcelable(EXTRA_PRINT_JOB);
if (printJob == null) {
throw new IllegalArgumentException("printJob cannot be null");
}
mPrintJobId = printJob.getId();
mIPrintDocumentAdapter = extras.getBinder(EXTRA_PRINT_DOCUMENT_ADAPTER);
if (mIPrintDocumentAdapter == null) {
throw new IllegalArgumentException("PrintDocumentAdapter cannot be null");
}
PrintAttributes attributes = getIntent().getParcelableExtra(EXTRA_PRINT_ATTRIBUTES);
PrintAttributes attributes = printJob.getAttributes();
if (attributes != null) {
mCurrPrintAttributes.copyFrom(attributes);
}

View File

@@ -37,6 +37,7 @@ import android.print.PrintAttributes.Margins;
import android.print.PrintAttributes.MediaSize;
import android.print.PrintAttributes.Resolution;
import android.print.PrintDocumentInfo;
import android.print.PrintJobId;
import android.print.PrintJobInfo;
import android.print.PrintManager;
import android.print.PrinterId;
@@ -51,6 +52,8 @@ import com.android.internal.os.HandlerCaller;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.FastXmlSerializer;
import libcore.io.IoUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -63,8 +66,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import libcore.io.IoUtils;
/**
* Service for exposing some of the {@link PrintSpooler} functionality to
* another process.
@@ -73,7 +74,7 @@ public final class PrintSpoolerService extends Service {
private static final String LOG_TAG = "PrintSpoolerService";
private static final boolean DEBUG_PRINT_JOB_LIFECYCLE = false;
private static final boolean DEBUG_PRINT_JOB_LIFECYCLE = true;
private static final boolean DEBUG_PERSISTENCE = false;
@@ -91,10 +92,6 @@ public final class PrintSpoolerService extends Service {
private static PrintSpoolerService sInstance;
private static int sPrintJobIdCounter;
private Intent mStartPrintJobConfigActivityIntent;
private IPrintSpoolerClient mClient;
private HandlerCaller mHandlerCaller;
@@ -112,8 +109,6 @@ public final class PrintSpoolerService extends Service {
@Override
public void onCreate() {
super.onCreate();
mStartPrintJobConfigActivityIntent = new Intent(PrintSpoolerService.this,
PrintJobConfigActivity.class);
mHandlerCaller = new HandlerCaller(this, getMainLooper(),
new HandlerCallerCallback(), false);
@@ -147,7 +142,7 @@ public final class PrintSpoolerService extends Service {
}
@Override
public void getPrintJobInfo(int printJobId, IPrintSpoolerCallbacks callback,
public void getPrintJobInfo(PrintJobId printJobId, IPrintSpoolerCallbacks callback,
int appId, int sequence) throws RemoteException {
PrintJobInfo printJob = null;
try {
@@ -159,38 +154,28 @@ public final class PrintSpoolerService extends Service {
@SuppressWarnings("deprecation")
@Override
public void createPrintJob(String printJobName, IPrintClient client,
IPrintDocumentAdapter printAdapter, PrintAttributes attributes,
IPrintSpoolerCallbacks callback, int appId, int sequence)
throws RemoteException {
PrintJobInfo printJob = null;
try {
printJob = PrintSpoolerService.this.createPrintJob(
printJobName, client, attributes, appId);
if (printJob != null) {
Intent intent = mStartPrintJobConfigActivityIntent;
intent.putExtra(PrintJobConfigActivity.EXTRA_PRINT_DOCUMENT_ADAPTER,
printAdapter.asBinder());
intent.putExtra(PrintJobConfigActivity.EXTRA_PRINT_JOB_ID,
printJob.getId());
intent.putExtra(PrintJobConfigActivity.EXTRA_PRINT_ATTRIBUTES, attributes);
public void createPrintJob(PrintJobInfo printJob, IPrintClient client,
IPrintDocumentAdapter printAdapter) throws RemoteException {
PrintSpoolerService.this.createPrintJob(printJob);
IntentSender sender = PendingIntent.getActivity(
PrintSpoolerService.this, 0, intent, PendingIntent.FLAG_ONE_SHOT
| PendingIntent.FLAG_CANCEL_CURRENT).getIntentSender();
Intent intent = new Intent(printJob.getId().flattenToString());
intent.setClass(PrintSpoolerService.this, PrintJobConfigActivity.class);
intent.putExtra(PrintJobConfigActivity.EXTRA_PRINT_DOCUMENT_ADAPTER,
printAdapter.asBinder());
intent.putExtra(PrintJobConfigActivity.EXTRA_PRINT_JOB, printJob);
Message message = mHandlerCaller.obtainMessageOO(
HandlerCallerCallback.MSG_START_PRINT_JOB_CONFIG_ACTIVITY,
client, sender);
mHandlerCaller.executeOrSendMessage(message);
}
} finally {
callback.onCreatePrintJobResult(printJob, sequence);
}
IntentSender sender = PendingIntent.getActivity(
PrintSpoolerService.this, 0, intent, PendingIntent.FLAG_ONE_SHOT
| PendingIntent.FLAG_CANCEL_CURRENT).getIntentSender();
Message message = mHandlerCaller.obtainMessageOO(
HandlerCallerCallback.MSG_START_PRINT_JOB_CONFIG_ACTIVITY,
client, sender);
mHandlerCaller.executeOrSendMessage(message);
}
@Override
public void setPrintJobState(int printJobId, int state, String error,
public void setPrintJobState(PrintJobId printJobId, int state, String error,
IPrintSpoolerCallbacks callback, int sequece) throws RemoteException {
boolean success = false;
try {
@@ -202,7 +187,7 @@ public final class PrintSpoolerService extends Service {
}
@Override
public void setPrintJobTag(int printJobId, String tag,
public void setPrintJobTag(PrintJobId printJobId, String tag,
IPrintSpoolerCallbacks callback, int sequece) throws RemoteException {
boolean success = false;
try {
@@ -213,7 +198,7 @@ public final class PrintSpoolerService extends Service {
}
@Override
public void writePrintJobData(ParcelFileDescriptor fd, int printJobId) {
public void writePrintJobData(ParcelFileDescriptor fd, PrintJobId printJobId) {
PrintSpoolerService.this.writePrintJobData(fd, printJobId);
}
@@ -223,6 +208,16 @@ public final class PrintSpoolerService extends Service {
HandlerCallerCallback.MSG_SET_CLIENT, client);
mHandlerCaller.executeOrSendMessage(message);
}
@Override
public void removeObsoletePrintJobs() {
PrintSpoolerService.this.removeObsoletePrintJobs();
}
@Override
public void forgetPrintJobs(List<PrintJobId> printJobIds) {
PrintSpoolerService.this.forgetPrintJobs(printJobIds);
}
};
}
@@ -351,15 +346,16 @@ public final class PrintSpoolerService extends Service {
private boolean isStateVisibleToUser(int state) {
return (isActiveState(state) && (state == PrintJobInfo.STATE_FAILED
|| state == PrintJobInfo.STATE_COMPLETED|| state == PrintJobInfo.STATE_CANCELED));
|| state == PrintJobInfo.STATE_COMPLETED || state == PrintJobInfo.STATE_CANCELED
|| state == PrintJobInfo.STATE_BLOCKED));
}
public PrintJobInfo getPrintJobInfo(int printJobId, int appId) {
public PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId) {
synchronized (mLock) {
final int printJobCount = mPrintJobs.size();
for (int i = 0; i < printJobCount; i++) {
PrintJobInfo printJob = mPrintJobs.get(i);
if (printJob.getId() == printJobId
if (printJob.getId().equals(printJobId)
&& (appId == PrintManager.APP_ID_ANY
|| appId == printJob.getAppId())) {
return printJob;
@@ -369,20 +365,9 @@ public final class PrintSpoolerService extends Service {
}
}
public PrintJobInfo createPrintJob(String label, IPrintClient client,
PrintAttributes attributes, int appId) {
public void createPrintJob(PrintJobInfo printJob) {
synchronized (mLock) {
final int printJobId = generatePrintJobIdLocked();
PrintJobInfo printJob = new PrintJobInfo();
printJob.setId(printJobId);
printJob.setAppId(appId);
printJob.setLabel(label);
printJob.setAttributes(attributes);
printJob.setState(PrintJobInfo.STATE_CREATED);
addPrintJobLocked(printJob);
return printJob;
}
}
@@ -404,8 +389,7 @@ public final class PrintSpoolerService extends Service {
// decide whether to restart the job or just cancel it.
setPrintJobState(printJob.getId(), PrintJobInfo.STATE_FAILED,
getString(R.string.no_connection_to_printer));
}
break;
} break;
}
}
}
@@ -418,26 +402,7 @@ public final class PrintSpoolerService extends Service {
}
}
private int generatePrintJobIdLocked() {
int printJobId = sPrintJobIdCounter++;
while (isDuplicatePrintJobId(printJobId)) {
printJobId = sPrintJobIdCounter++;
}
return printJobId;
}
private boolean isDuplicatePrintJobId(int printJobId) {
final int printJobCount = mPrintJobs.size();
for (int j = 0; j < printJobCount; j++) {
PrintJobInfo printJob = mPrintJobs.get(j);
if (printJob.getId() == printJobId) {
return true;
}
}
return false;
}
public void writePrintJobData(final ParcelFileDescriptor fd, final int printJobId) {
public void writePrintJobData(final ParcelFileDescriptor fd, final PrintJobId printJobId) {
final PrintJobInfo printJob;
synchronized (mLock) {
printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
@@ -476,9 +441,9 @@ public final class PrintSpoolerService extends Service {
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
}
public File generateFileForPrintJob(int printJobId) {
public File generateFileForPrintJob(PrintJobId printJobId) {
return new File(getFilesDir(), "print_job_"
+ printJobId + "." + PRINT_FILE_EXTENSION);
+ printJobId.flattenToString() + "." + PRINT_FILE_EXTENSION);
}
private void addPrintJobLocked(PrintJobInfo printJob) {
@@ -488,16 +453,59 @@ public final class PrintSpoolerService extends Service {
}
}
private void removePrintJobLocked(PrintJobInfo printJob) {
if (mPrintJobs.remove(printJob)) {
generateFileForPrintJob(printJob.getId()).delete();
if (DEBUG_PRINT_JOB_LIFECYCLE) {
Slog.i(LOG_TAG, "[REMOVE] " + printJob);
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();
}
}
}
public boolean setPrintJobState(int printJobId, int state, String error) {
private void removeObsoletePrintJobs() {
synchronized (mLock) {
final int printJobCount = mPrintJobs.size();
for (int i = printJobCount - 1; i >= 0; i--) {
PrintJobInfo printJob = mPrintJobs.get(i);
if (isObsoleteState(printJob.getState())) {
mPrintJobs.remove(i);
if (DEBUG_PRINT_JOB_LIFECYCLE) {
Slog.i(LOG_TAG, "[REMOVE] " + printJob.getId().flattenToString());
}
removePrintJobFileLocked(printJob.getId());
}
}
mPersistanceManager.writeStateLocked();
}
}
private void removePrintJobFileLocked(PrintJobId printJobId) {
File file = generateFileForPrintJob(printJobId);
if (file.exists()) {
file.delete();
if (DEBUG_PRINT_JOB_LIFECYCLE) {
Slog.i(LOG_TAG, "[REMOVE FILE FOR] " + printJobId.flattenToString());
}
}
}
public boolean setPrintJobState(PrintJobId printJobId, int state, String error) {
boolean success = false;
synchronized (mLock) {
@@ -516,7 +524,11 @@ public final class PrintSpoolerService extends Service {
switch (state) {
case PrintJobInfo.STATE_COMPLETED:
case PrintJobInfo.STATE_CANCELED:
removePrintJobLocked(printJob);
// 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.
removePrintJobFileLocked(printJob.getId());
// $fall-through$
case PrintJobInfo.STATE_FAILED: {
@@ -570,6 +582,11 @@ public final class PrintSpoolerService extends Service {
return false;
}
private boolean isObsoleteState(int printJobState) {
return (isTeminalState(printJobState)
|| printJobState == PrintJobInfo.STATE_QUEUED);
}
private boolean isActiveState(int printJobState) {
return printJobState == PrintJobInfo.STATE_CREATED
|| printJobState == PrintJobInfo.STATE_QUEUED
@@ -577,7 +594,12 @@ public final class PrintSpoolerService extends Service {
|| printJobState == PrintJobInfo.STATE_BLOCKED;
}
public boolean setPrintJobTag(int printJobId, String tag) {
private boolean isTeminalState(int printJobState) {
return printJobState == PrintJobInfo.STATE_COMPLETED
|| printJobState == PrintJobInfo.STATE_CANCELED;
}
public boolean setPrintJobTag(PrintJobId printJobId, String tag) {
synchronized (mLock) {
PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
if (printJob != null) {
@@ -599,7 +621,7 @@ public final class PrintSpoolerService extends Service {
return false;
}
public void setPrintJobCopiesNoPersistence(int printJobId, int copies) {
public void setPrintJobCopiesNoPersistence(PrintJobId printJobId, int copies) {
synchronized (mLock) {
PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
if (printJob != null) {
@@ -608,7 +630,8 @@ public final class PrintSpoolerService extends Service {
}
}
public void setPrintJobPrintDocumentInfoNoPersistence(int printJobId, PrintDocumentInfo info) {
public void setPrintJobPrintDocumentInfoNoPersistence(PrintJobId printJobId,
PrintDocumentInfo info) {
synchronized (mLock) {
PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
if (printJob != null) {
@@ -617,7 +640,8 @@ public final class PrintSpoolerService extends Service {
}
}
public void setPrintJobAttributesNoPersistence(int printJobId, PrintAttributes attributes) {
public void setPrintJobAttributesNoPersistence(PrintJobId printJobId,
PrintAttributes attributes) {
synchronized (mLock) {
PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
if (printJob != null) {
@@ -626,7 +650,7 @@ public final class PrintSpoolerService extends Service {
}
}
public void setPrintJobPrinterNoPersistence(int printJobId, PrinterInfo printer) {
public void setPrintJobPrinterNoPersistence(PrintJobId printJobId, PrinterInfo printer) {
synchronized (mLock) {
PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
if (printJob != null) {
@@ -636,7 +660,7 @@ public final class PrintSpoolerService extends Service {
}
}
public void setPrintJobPagesNoPersistence(int printJobId, PageRange[] pages) {
public void setPrintJobPagesNoPersistence(PrintJobId printJobId, PageRange[] pages) {
synchronized (mLock) {
PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
if (printJob != null) {
@@ -759,15 +783,9 @@ public final class PrintSpoolerService extends Service {
for (int j = 0; j < printJobCount; j++) {
PrintJobInfo printJob = printJobs.get(j);
final int state = printJob.getState();
if (state < PrintJobInfo.STATE_QUEUED
|| state > PrintJobInfo.STATE_CANCELED) {
continue;
}
serializer.startTag(null, TAG_JOB);
serializer.attribute(null, ATTR_ID, String.valueOf(printJob.getId()));
serializer.attribute(null, ATTR_ID, printJob.getId().flattenToString());
serializer.attribute(null, ATTR_LABEL, printJob.getLabel().toString());
serializer.attribute(null, ATTR_STATE, String.valueOf(printJob.getState()));
serializer.attribute(null, ATTR_APP_ID, String.valueOf(printJob.getAppId()));
@@ -948,7 +966,8 @@ public final class PrintSpoolerService extends Service {
PrintJobInfo printJob = new PrintJobInfo();
final int printJobId = Integer.parseInt(parser.getAttributeValue(null, ATTR_ID));
PrintJobId printJobId = PrintJobId.unflattenFromString(
parser.getAttributeValue(null, ATTR_ID));
printJob.setId(printJobId);
String label = parser.getAttributeValue(null, ATTR_LABEL);
printJob.setLabel(label);

View File

@@ -33,6 +33,7 @@ import android.print.IPrintDocumentAdapter;
import android.print.IPrintManager;
import android.print.IPrinterDiscoveryObserver;
import android.print.PrintAttributes;
import android.print.PrintJobId;
import android.print.PrintJobInfo;
import android.print.PrinterId;
import android.printservice.PrintServiceInfo;
@@ -70,30 +71,32 @@ public final class PrintManagerService extends IPrintManager.Stub {
BackgroundThread.getHandler().post(new Runnable() {
@Override
public void run() {
final UserState userState;
synchronized (mLock) {
UserState userState = getCurrentUserStateLocked();
userState = getCurrentUserStateLocked();
userState.updateIfNeededLocked();
userState.getSpoolerLocked().start();
}
// This is the first time we switch to this user after boot, so
// now is the time to remove obsolete print jobs since they
// are from the last boot and no application would query them.
userState.removeObsoletePrintJobs();
}
});
}
@Override
public PrintJobInfo print(String printJobName, IPrintClient client,
IPrintDocumentAdapter documentAdapter, PrintAttributes attributes, int appId,
int userId) {
public PrintJobInfo print(String printJobName, final IPrintClient client,
final IPrintDocumentAdapter documentAdapter, PrintAttributes attributes,
int appId, int userId) {
final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
final RemotePrintSpooler spooler;
synchronized (mLock) {
userState = getOrCreateUserStateLocked(resolvedUserId);
spooler = userState.getSpoolerLocked();
}
final long identity = Binder.clearCallingIdentity();
try {
return spooler.createPrintJob(printJobName, client, documentAdapter,
return userState.print(printJobName, client, documentAdapter,
attributes, resolvedAppId);
} finally {
Binder.restoreCallingIdentity(identity);
@@ -105,95 +108,65 @@ public final class PrintManagerService extends IPrintManager.Stub {
final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
final RemotePrintSpooler spooler;
synchronized (mLock) {
userState = getOrCreateUserStateLocked(resolvedUserId);
spooler = userState.getSpoolerLocked();
}
final long identity = Binder.clearCallingIdentity();
try {
return spooler.getPrintJobInfos(null, PrintJobInfo.STATE_ANY,
resolvedAppId);
return userState.getPrintJobInfos(resolvedAppId);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public PrintJobInfo getPrintJobInfo(int printJobId, int appId, int userId) {
public PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId, int userId) {
final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
final RemotePrintSpooler spooler;
synchronized (mLock) {
userState = getOrCreateUserStateLocked(resolvedUserId);
spooler = userState.getSpoolerLocked();
}
final long identity = Binder.clearCallingIdentity();
try {
return spooler.getPrintJobInfo(printJobId, resolvedAppId);
return userState.getPrintJobInfo(printJobId, resolvedAppId);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void cancelPrintJob(int printJobId, int appId, int userId) {
public void cancelPrintJob(PrintJobId printJobId, int appId, int userId) {
final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
final RemotePrintSpooler spooler;
synchronized (mLock) {
userState = getOrCreateUserStateLocked(resolvedUserId);
spooler = userState.getSpoolerLocked();
}
final long identity = Binder.clearCallingIdentity();
try {
PrintJobInfo printJobInfo = spooler.getPrintJobInfo(printJobId, resolvedAppId);
if (printJobInfo == null) {
return;
}
if (printJobInfo.getState() != PrintJobInfo.STATE_FAILED) {
ComponentName printServiceName = printJobInfo.getPrinterId().getServiceName();
RemotePrintService printService = null;
synchronized (mLock) {
printService = userState.getActiveServicesLocked().get(printServiceName);
}
if (printService == null) {
return;
}
printService.onRequestCancelPrintJob(printJobInfo);
} else {
// If the print job is failed we do not need cooperation
// from the print service.
spooler.setPrintJobState(printJobId, PrintJobInfo.STATE_CANCELED, null);
}
userState.cancelPrintJob(printJobId, resolvedAppId);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void restartPrintJob(int printJobId, int appId, int userId) {
public void restartPrintJob(PrintJobId printJobId, int appId, int userId) {
final int resolvedAppId = resolveCallingAppEnforcingPermissions(appId);
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final RemotePrintSpooler spooler;
final UserState userState;
synchronized (mLock) {
spooler = getOrCreateUserStateLocked(resolvedUserId).getSpoolerLocked();
userState = getOrCreateUserStateLocked(resolvedUserId);
}
final long identity = Binder.clearCallingIdentity();
try {
PrintJobInfo printJobInfo = getPrintJobInfo(printJobId, resolvedAppId, resolvedUserId);
if (printJobInfo == null || printJobInfo.getState() != PrintJobInfo.STATE_FAILED) {
return;
}
spooler.setPrintJobState(printJobId, PrintJobInfo.STATE_QUEUED, null);
userState.restartPrintJob(printJobId, resolvedAppId);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public List<PrintServiceInfo> getEnabledPrintServices(int userId) {
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
@@ -443,6 +416,7 @@ public final class PrintManagerService extends IPrintManager.Stub {
// user changes
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
intentFilter.addAction(Intent.ACTION_USER_REMOVED);
mContext.registerReceiverAsUser(new BroadcastReceiver() {
@Override
@@ -471,15 +445,24 @@ public final class PrintManagerService extends IPrintManager.Stub {
}
private void switchUser(int newUserId) {
UserState userState;
synchronized (mLock) {
if (newUserId == mCurrentUserId) {
return;
}
mCurrentUserId = newUserId;
UserState userState = getCurrentUserStateLocked();
userState.updateIfNeededLocked();
userState.getSpoolerLocked().start();
userState = mUserStates.get(mCurrentUserId);
if (userState == null) {
userState = getCurrentUserStateLocked();
userState.updateIfNeededLocked();
} else {
userState.updateIfNeededLocked();
}
}
// This is the first time we switch to this user after boot, so
// now is the time to remove obsolete print jobs since they
// are from the last boot and no application would query them.
userState.removeObsoletePrintJobs();
}
private void removeUser(int removedUserId) {

View File

@@ -20,6 +20,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ParceledListSlice;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -29,6 +30,7 @@ import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.UserHandle;
import android.print.PrintJobId;
import android.print.PrintJobInfo;
import android.print.PrintManager;
import android.print.PrinterId;
@@ -690,7 +692,7 @@ final class RemotePrintService implements DeathRecipient {
}
@Override
public PrintJobInfo getPrintJobInfo(int printJobId) {
public PrintJobInfo getPrintJobInfo(PrintJobId printJobId) {
RemotePrintService service = mWeakService.get();
if (service != null) {
final long identity = Binder.clearCallingIdentity();
@@ -705,7 +707,7 @@ final class RemotePrintService implements DeathRecipient {
}
@Override
public boolean setPrintJobState(int printJobId, int state, String error) {
public boolean setPrintJobState(PrintJobId printJobId, int state, String error) {
RemotePrintService service = mWeakService.get();
if (service != null) {
final long identity = Binder.clearCallingIdentity();
@@ -719,7 +721,7 @@ final class RemotePrintService implements DeathRecipient {
}
@Override
public boolean setPrintJobTag(int printJobId, String tag) {
public boolean setPrintJobTag(PrintJobId printJobId, String tag) {
RemotePrintService service = mWeakService.get();
if (service != null) {
final long identity = Binder.clearCallingIdentity();
@@ -733,7 +735,7 @@ final class RemotePrintService implements DeathRecipient {
}
@Override
public void writePrintJobData(ParcelFileDescriptor fd, int printJobId) {
public void writePrintJobData(ParcelFileDescriptor fd, PrintJobId printJobId) {
RemotePrintService service = mWeakService.get();
if (service != null) {
final long identity = Binder.clearCallingIdentity();
@@ -746,13 +748,15 @@ final class RemotePrintService implements DeathRecipient {
}
@Override
public void onPrintersAdded(List<PrinterInfo> printers) {
@SuppressWarnings({"rawtypes", "unchecked"})
public void onPrintersAdded(ParceledListSlice printers) {
RemotePrintService service = mWeakService.get();
if (service != null) {
throwIfPrinterIdsForPrinterInfoTampered(service.mComponentName, printers);
List<PrinterInfo> addedPrinters = (List<PrinterInfo>) printers.getList();
throwIfPrinterIdsForPrinterInfoTampered(service.mComponentName, addedPrinters);
final long identity = Binder.clearCallingIdentity();
try {
service.mCallbacks.onPrintersAdded(printers);
service.mCallbacks.onPrintersAdded(addedPrinters);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -760,13 +764,15 @@ final class RemotePrintService implements DeathRecipient {
}
@Override
public void onPrintersRemoved(List<PrinterId> printerIds) {
@SuppressWarnings({"rawtypes", "unchecked"})
public void onPrintersRemoved(ParceledListSlice printerIds) {
RemotePrintService service = mWeakService.get();
if (service != null) {
throwIfPrinterIdsTampered(service.mComponentName, printerIds);
List<PrinterId> removedPrinterIds = (List<PrinterId>) printerIds.getList();
throwIfPrinterIdsTampered(service.mComponentName, removedPrinterIds);
final long identity = Binder.clearCallingIdentity();
try {
service.mCallbacks.onPrintersRemoved(printerIds);
service.mCallbacks.onPrintersRemoved(removedPrinterIds);
} finally {
Binder.restoreCallingIdentity(identity);
}

View File

@@ -31,20 +31,20 @@ import android.print.IPrintDocumentAdapter;
import android.print.IPrintSpooler;
import android.print.IPrintSpoolerCallbacks;
import android.print.IPrintSpoolerClient;
import android.print.PrintAttributes;
import android.print.PrintJobId;
import android.print.PrintJobInfo;
import android.print.PrintManager;
import android.util.Slog;
import android.util.TimedRemoteCaller;
import libcore.io.IoUtils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.concurrent.TimeoutException;
import libcore.io.IoUtils;
/**
* This represents the remote print spooler as a local object to the
* PrintManagerSerivce. It is responsible to connecting to the remote
@@ -64,8 +64,6 @@ final class RemotePrintSpooler {
private final GetPrintJobInfosCaller mGetPrintJobInfosCaller = new GetPrintJobInfosCaller();
private final CreatePrintJobCaller mCreatePrintJobCaller = new CreatePrintJobCaller();
private final GetPrintJobInfoCaller mGetPrintJobInfoCaller = new GetPrintJobInfoCaller();
private final SetPrintJobStateCaller mSetPrintJobStatusCaller = new SetPrintJobStateCaller();
@@ -132,16 +130,15 @@ final class RemotePrintSpooler {
return null;
}
public final PrintJobInfo createPrintJob(String printJobName, IPrintClient client,
IPrintDocumentAdapter documentAdapter, PrintAttributes attributes, int appId) {
public final void createPrintJob(PrintJobInfo printJob, IPrintClient client,
IPrintDocumentAdapter documentAdapter) {
throwIfCalledOnMainThread();
synchronized (mLock) {
throwIfDestroyedLocked();
mCanUnbind = false;
}
try {
return mCreatePrintJobCaller.createPrintJob(getRemoteInstanceLazy(),
printJobName, client, documentAdapter, attributes, appId);
getRemoteInstanceLazy().createPrintJob(printJob, client, documentAdapter);
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error creating print job.", re);
} catch (TimeoutException te) {
@@ -155,10 +152,9 @@ final class RemotePrintSpooler {
mLock.notifyAll();
}
}
return null;
}
public final void writePrintJobData(ParcelFileDescriptor fd, int printJobId) {
public final void writePrintJobData(ParcelFileDescriptor fd, PrintJobId printJobId) {
throwIfCalledOnMainThread();
synchronized (mLock) {
throwIfDestroyedLocked();
@@ -184,7 +180,7 @@ final class RemotePrintSpooler {
}
}
public final PrintJobInfo getPrintJobInfo(int printJobId, int appId) {
public final PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId) {
throwIfCalledOnMainThread();
synchronized (mLock) {
throwIfDestroyedLocked();
@@ -209,7 +205,7 @@ final class RemotePrintSpooler {
return null;
}
public final boolean setPrintJobState(int printJobId, int state, String error) {
public final boolean setPrintJobState(PrintJobId printJobId, int state, String error) {
throwIfCalledOnMainThread();
synchronized (mLock) {
throwIfDestroyedLocked();
@@ -234,7 +230,7 @@ final class RemotePrintSpooler {
return false;
}
public final boolean setPrintJobTag(int printJobId, String tag) {
public final boolean setPrintJobTag(PrintJobId printJobId, String tag) {
throwIfCalledOnMainThread();
synchronized (mLock) {
throwIfDestroyedLocked();
@@ -259,19 +255,46 @@ final class RemotePrintSpooler {
return false;
}
public final void start() {
public final void removeObsoletePrintJobs() {
throwIfCalledOnMainThread();
synchronized (mLock) {
throwIfDestroyedLocked();
mCanUnbind = false;
}
try {
getRemoteInstanceLazy();
getRemoteInstanceLazy().removeObsoletePrintJobs();
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error removing obsolete print jobs .", re);
} catch (TimeoutException te) {
Slog.e(LOG_TAG, "Error starting the spooler.", te);
Slog.e(LOG_TAG, "Error removing obsolete print jobs .", te);
} finally {
if (DEBUG) {
Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] start()");
Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier()
+ "] removeObsoletePrintJobs()");
}
synchronized (mLock) {
mCanUnbind = true;
mLock.notifyAll();
}
}
}
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;
@@ -333,6 +356,9 @@ final class RemotePrintSpooler {
}
private void bindLocked() throws TimeoutException {
if (mRemoteInstance != null) {
return;
}
if (DEBUG) {
Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] bindLocked()");
}
@@ -362,6 +388,9 @@ final class RemotePrintSpooler {
}
private void unbindLocked() {
if (mRemoteInstance == null) {
return;
}
while (true) {
if (mCanUnbind) {
if (DEBUG) {
@@ -452,29 +481,6 @@ final class RemotePrintSpooler {
}
}
private static final class CreatePrintJobCaller extends TimedRemoteCaller<PrintJobInfo> {
private final IPrintSpoolerCallbacks mCallback;
public CreatePrintJobCaller() {
super(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS);
mCallback = new BasePrintSpoolerServiceCallbacks() {
@Override
public void onCreatePrintJobResult(PrintJobInfo printJob, int sequence) {
onRemoteMethodResult(printJob, sequence);
}
};
}
public PrintJobInfo createPrintJob(IPrintSpooler target, String printJobName,
IPrintClient client, IPrintDocumentAdapter documentAdapter,
PrintAttributes attributes, int appId) throws RemoteException, TimeoutException {
final int sequence = onBeforeRemoteCall();
target.createPrintJob(printJobName, client, documentAdapter, attributes,
mCallback, appId, sequence);
return getResultTimed(sequence);
}
}
private static final class GetPrintJobInfoCaller extends TimedRemoteCaller<PrintJobInfo> {
private final IPrintSpoolerCallbacks mCallback;
@@ -488,7 +494,7 @@ final class RemotePrintSpooler {
};
}
public PrintJobInfo getPrintJobInfo(IPrintSpooler target, int printJobId,
public PrintJobInfo getPrintJobInfo(IPrintSpooler target, PrintJobId printJobId,
int appId) throws RemoteException, TimeoutException {
final int sequence = onBeforeRemoteCall();
target.getPrintJobInfo(printJobId, mCallback, appId, sequence);
@@ -509,7 +515,7 @@ final class RemotePrintSpooler {
};
}
public boolean setPrintJobState(IPrintSpooler target, int printJobId,
public boolean setPrintJobState(IPrintSpooler target, PrintJobId printJobId,
int status, String error) throws RemoteException, TimeoutException {
final int sequence = onBeforeRemoteCall();
target.setPrintJobState(printJobId, status, error, mCallback, sequence);
@@ -530,7 +536,7 @@ final class RemotePrintSpooler {
};
}
public boolean setPrintJobTag(IPrintSpooler target, int printJobId,
public boolean setPrintJobTag(IPrintSpooler target, PrintJobId printJobId,
String tag) throws RemoteException, TimeoutException {
final int sequence = onBeforeRemoteCall();
target.setPrintJobTag(printJobId, tag, mCallback, sequence);
@@ -550,11 +556,6 @@ final class RemotePrintSpooler {
/* do nothing */
}
@Override
public void onCreatePrintJobResult(PrintJobInfo printJob, int sequence) {
/* do nothing */
}
@Override
public void onCancelPrintJobResult(boolean canceled, int sequence) {
/* do nothing */

View File

@@ -21,17 +21,24 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
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.IPrinterDiscoveryObserver;
import android.print.PrintAttributes;
import android.print.PrintJobId;
import android.print.PrintJobInfo;
import android.print.PrintManager;
import android.print.PrinterId;
@@ -46,6 +53,7 @@ import android.util.Log;
import android.util.Slog;
import com.android.internal.R;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.SomeArgs;
import com.android.server.print.RemotePrintService.PrintServiceCallbacks;
import com.android.server.print.RemotePrintSpooler.PrintSpoolerCallbacks;
@@ -56,7 +64,6 @@ import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
@@ -68,8 +75,6 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
private static final boolean DEBUG = false;
private static final int MAX_ITEMS_PER_CALLBACK = 50;
private static final char COMPONENT_NAME_SEPARATOR = ':';
private final SimpleStringSplitter mStringColonSplitter =
@@ -87,6 +92,9 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
private final Set<ComponentName> mEnabledServices =
new ArraySet<ComponentName>();
private final CreatedPrintJobTracker mCreatedPrintJobTracker =
new CreatedPrintJobTracker();
private final Object mLock;
private final Context mContext;
@@ -134,6 +142,79 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
}
}
public void removeObsoletePrintJobs() {
mSpooler.removeObsoletePrintJobs();
}
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.setAppId(appId);
printJob.setLabel(printJobName);
printJob.setAttributes(attributes);
printJob.setState(PrintJobInfo.STATE_CREATED);
// Spin the spooler to add the job and show the config UI.
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
mSpooler.createPrintJob(printJob, client, documentAdapter);
return null;
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
return printJob;
}
public List<PrintJobInfo> getPrintJobInfos(int appId) {
return mSpooler.getPrintJobInfos(null, PrintJobInfo.STATE_ANY, appId);
}
public PrintJobInfo getPrintJobInfo(PrintJobId printJobId, int appId) {
return mSpooler.getPrintJobInfo(printJobId, appId);
}
public void cancelPrintJob(PrintJobId printJobId, int appId) {
PrintJobInfo printJobInfo = mSpooler.getPrintJobInfo(printJobId, appId);
if (printJobInfo == null) {
return;
}
if (printJobInfo.getState() != PrintJobInfo.STATE_FAILED) {
ComponentName printServiceName = printJobInfo.getPrinterId().getServiceName();
RemotePrintService printService = null;
synchronized (mLock) {
printService = mActiveServices.get(printServiceName);
}
if (printService == null) {
return;
}
printService.onRequestCancelPrintJob(printJobInfo);
} else {
// If the print job is failed we do not need cooperation
// from the print service.
mSpooler.setPrintJobState(printJobId, PrintJobInfo.STATE_CANCELED, null);
}
}
public void restartPrintJob(PrintJobId printJobId, int appId) {
PrintJobInfo printJobInfo = getPrintJobInfo(printJobId, appId);
if (printJobInfo == null || printJobInfo.getState() != PrintJobInfo.STATE_FAILED) {
return;
}
mSpooler.setPrintJobState(printJobId, PrintJobInfo.STATE_QUEUED, null);
}
public List<PrintServiceInfo> getEnabledPrintServices() {
synchronized (mLock) {
List<PrintServiceInfo> enabledServices = null;
@@ -328,18 +409,6 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
}
}
public RemotePrintSpooler getSpoolerLocked() {
throwIfDestroyedLocked();
return mSpooler;
}
public Map<ComponentName, RemotePrintService> getActiveServicesLocked() {
synchronized(mLock) {
throwIfDestroyedLocked();
return mActiveServices;
}
}
public Set<ComponentName> getEnabledServices() {
synchronized(mLock) {
throwIfDestroyedLocked();
@@ -593,13 +662,12 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
// just died. Do this off the main thread since we do to allow
// calls into the spooler on the main thread.
if (Looper.getMainLooper().isCurrentThread()) {
new AsyncTask<Void, Void, Void>() {
BackgroundThread.getHandler().post(new Runnable() {
@Override
protected Void doInBackground(Void... params) {
public void run() {
failActivePrintJobsForServiceInternal(serviceName);
return null;
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
});
} else {
failActivePrintJobsForServiceInternal(serviceName);
}
@@ -1088,19 +1156,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
private void handlePrintersAdded(IPrinterDiscoveryObserver observer,
List<PrinterInfo> printers) {
try {
final int printerCount = printers.size();
if (printerCount <= MAX_ITEMS_PER_CALLBACK) {
observer.onPrintersAdded(printers);
} else {
// Send the added printers in chunks avoiding the binder transaction limit.
final int transactionCount = (printerCount / MAX_ITEMS_PER_CALLBACK) + 1;
for (int i = 0; i < transactionCount; i++) {
final int start = i * MAX_ITEMS_PER_CALLBACK;
final int end = Math.min(start + MAX_ITEMS_PER_CALLBACK, printerCount);
List<PrinterInfo> subPrinters = printers.subList(start, end);
observer.onPrintersAdded(subPrinters);
}
}
observer.onPrintersAdded(new ParceledListSlice<PrinterInfo>(printers));
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error sending added printers", re);
}
@@ -1109,21 +1165,9 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
private void handlePrintersRemoved(IPrinterDiscoveryObserver observer,
List<PrinterId> printerIds) {
try {
final int printerCount = printerIds.size();
if (printerCount <= MAX_ITEMS_PER_CALLBACK) {
observer.onPrintersRemoved(printerIds);
} else {
// Send the added printers in chunks avoiding the binder transaction limit.
final int transactionCount = (printerCount / MAX_ITEMS_PER_CALLBACK) + 1;
for (int i = 0; i < transactionCount; i++) {
final int start = i * MAX_ITEMS_PER_CALLBACK;
final int end = Math.min(start + MAX_ITEMS_PER_CALLBACK, printerCount);
List<PrinterId> subPrinterIds = printerIds.subList(start, end);
observer.onPrintersRemoved(subPrinterIds);
}
}
observer.onPrintersRemoved(new ParceledListSlice<PrinterId>(printerIds));
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error sending added printers", re);
Log.e(LOG_TAG, "Error sending removed printers", re);
}
}
@@ -1255,4 +1299,51 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
}
}
}
}
private final class CreatedPrintJobTracker {
private final ArrayMap<IBinder, List<PrintJobId>> mCreatedPrintJobs =
new ArrayMap<IBinder, List<PrintJobId>>();
public boolean onPrintJobCreatedLocked(final IBinder creator, PrintJobId printJobId) {
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);
}
}
}, 0);
} catch (RemoteException re) {
/* The process is already dead - we just failed. */
return false;
}
synchronized (mLock) {
List<PrintJobId> printJobIds = mCreatedPrintJobs.get(creator);
if (printJobIds == null) {
printJobIds = new ArrayList<PrintJobId>();
mCreatedPrintJobs.put(creator, printJobIds);
}
printJobIds.add(printJobId);
}
return true;
}
}
}