am ef2088a2: Merge "Handle print serivce crashes." into klp-dev
* commit 'ef2088a26a42621329c6b9fecb323566e19490e4': Handle print serivce crashes.
This commit is contained in:
@@ -20,8 +20,6 @@ import android.os.Bundle;
|
|||||||
import android.os.CancellationSignal;
|
import android.os.CancellationSignal;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class that provides the content of a document to be printed.
|
* Base class that provides the content of a document to be printed.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import android.app.Service;
|
|||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ import java.util.Map;
|
|||||||
public class FusedPrintersProvider extends Loader<List<PrinterInfo>> {
|
public class FusedPrintersProvider extends Loader<List<PrinterInfo>> {
|
||||||
private static final String LOG_TAG = "FusedPrintersProvider";
|
private static final String LOG_TAG = "FusedPrintersProvider";
|
||||||
|
|
||||||
private static final boolean DEBUG = true && Build.IS_DEBUGGABLE;
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
private static final double WEIGHT_DECAY_COEFFICIENT = 0.95f;
|
private static final double WEIGHT_DECAY_COEFFICIENT = 0.95f;
|
||||||
|
|
||||||
|
|||||||
@@ -73,9 +73,9 @@ public final class PrintSpoolerService extends Service {
|
|||||||
|
|
||||||
private static final String LOG_TAG = "PrintSpoolerService";
|
private static final String LOG_TAG = "PrintSpoolerService";
|
||||||
|
|
||||||
private static final boolean DEBUG_PRINT_JOB_LIFECYCLE = true;
|
private static final boolean DEBUG_PRINT_JOB_LIFECYCLE = false;
|
||||||
|
|
||||||
private static final boolean DEBUG_PERSISTENCE = true;
|
private static final boolean DEBUG_PERSISTENCE = false;
|
||||||
|
|
||||||
private static final boolean PERSISTNECE_MANAGER_ENABLED = true;
|
private static final boolean PERSISTNECE_MANAGER_ENABLED = true;
|
||||||
|
|
||||||
@@ -838,18 +838,8 @@ public final class PrintSpoolerService extends Service {
|
|||||||
resolution.getHorizontalDpi()));
|
resolution.getHorizontalDpi()));
|
||||||
serializer.attribute(null, ATTR_VERTICAL_DPI, String.valueOf(
|
serializer.attribute(null, ATTR_VERTICAL_DPI, String.valueOf(
|
||||||
resolution.getVerticalDpi()));
|
resolution.getVerticalDpi()));
|
||||||
// We prefer to store only the package name and
|
serializer.attribute(null, ATTR_LABEL,
|
||||||
// resource id and fallback to the label.
|
resolution.getLabel(getPackageManager()));
|
||||||
if (!TextUtils.isEmpty(mediaSize.mPackageName)
|
|
||||||
&& resolution.mLabelResId > 0) {
|
|
||||||
serializer.attribute(null, ATTR_PACKAGE_NAME,
|
|
||||||
resolution.mPackageName);
|
|
||||||
serializer.attribute(null, ATTR_LABEL_RES_ID,
|
|
||||||
String.valueOf(resolution.mLabelResId));
|
|
||||||
} else {
|
|
||||||
serializer.attribute(null, ATTR_LABEL,
|
|
||||||
resolution.getLabel(getPackageManager()));
|
|
||||||
}
|
|
||||||
serializer.endTag(null, TAG_RESOLUTION);
|
serializer.endTag(null, TAG_RESOLUTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1047,11 +1037,7 @@ public final class PrintSpoolerService extends Service {
|
|||||||
ATTR_HORIZONTAL_DPI));
|
ATTR_HORIZONTAL_DPI));
|
||||||
final int verticalDpi = Integer.parseInt(parser.getAttributeValue(null,
|
final int verticalDpi = Integer.parseInt(parser.getAttributeValue(null,
|
||||||
ATTR_VERTICAL_DPI));
|
ATTR_VERTICAL_DPI));
|
||||||
String packageName = parser.getAttributeValue(null, ATTR_PACKAGE_NAME);
|
Resolution resolution = new Resolution(id, label, horizontalDpi, verticalDpi);
|
||||||
final int labelResId = Integer.parseInt(
|
|
||||||
parser.getAttributeValue(null, ATTR_LABEL_RES_ID));
|
|
||||||
Resolution resolution = new Resolution(id, label, packageName, labelResId,
|
|
||||||
horizontalDpi, verticalDpi);
|
|
||||||
builder.setResolution(resolution);
|
builder.setResolution(resolution);
|
||||||
parser.next();
|
parser.next();
|
||||||
skipEmptyTextTags(parser);
|
skipEmptyTextTags(parser);
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
package com.android.printspooler;
|
package com.android.printspooler;
|
||||||
|
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
@@ -43,7 +42,7 @@ import java.io.OutputStream;
|
|||||||
final class RemotePrintDocumentAdapter {
|
final class RemotePrintDocumentAdapter {
|
||||||
private static final String LOG_TAG = "RemotePrintDocumentAdapter";
|
private static final String LOG_TAG = "RemotePrintDocumentAdapter";
|
||||||
|
|
||||||
private static final boolean DEBUG = true && Build.IS_DEBUGGABLE;
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
private final IPrintDocumentAdapter mRemoteInterface;
|
private final IPrintDocumentAdapter mRemoteInterface;
|
||||||
|
|
||||||
|
|||||||
@@ -21,11 +21,9 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.IBinder.DeathRecipient;
|
import android.os.IBinder.DeathRecipient;
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
@@ -39,8 +37,6 @@ import android.printservice.IPrintService;
|
|||||||
import android.printservice.IPrintServiceClient;
|
import android.printservice.IPrintServiceClient;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
import com.android.internal.R;
|
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -55,7 +51,7 @@ final class RemotePrintService implements DeathRecipient {
|
|||||||
|
|
||||||
private static final String LOG_TAG = "RemotePrintService";
|
private static final String LOG_TAG = "RemotePrintService";
|
||||||
|
|
||||||
private static final boolean DEBUG = true && Build.IS_DEBUGGABLE;
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
|
||||||
@@ -65,7 +61,7 @@ final class RemotePrintService implements DeathRecipient {
|
|||||||
|
|
||||||
private final RemotePrintSpooler mSpooler;
|
private final RemotePrintSpooler mSpooler;
|
||||||
|
|
||||||
private final UserState mUserState;
|
private final PrintServiceCallbacks mCallbacks;
|
||||||
|
|
||||||
private final int mUserId;
|
private final int mUserId;
|
||||||
|
|
||||||
@@ -83,14 +79,24 @@ final class RemotePrintService implements DeathRecipient {
|
|||||||
|
|
||||||
private boolean mDestroyed;
|
private boolean mDestroyed;
|
||||||
|
|
||||||
private boolean mAllPrintJobsHandled;
|
private boolean mHasActivePrintJobs;
|
||||||
|
|
||||||
private boolean mHasPrinterDiscoverySession;
|
private boolean mHasPrinterDiscoverySession;
|
||||||
|
|
||||||
|
private List<PrinterId> mDiscoveryPriorityList;
|
||||||
|
|
||||||
|
private List<PrinterId> mTrackedPrinterList;
|
||||||
|
|
||||||
|
public static interface PrintServiceCallbacks {
|
||||||
|
public void onPrintersAdded(List<PrinterInfo> printers);
|
||||||
|
public void onPrintersRemoved(List<PrinterId> printerIds);
|
||||||
|
public void onServiceDied(RemotePrintService service);
|
||||||
|
}
|
||||||
|
|
||||||
public RemotePrintService(Context context, ComponentName componentName, int userId,
|
public RemotePrintService(Context context, ComponentName componentName, int userId,
|
||||||
RemotePrintSpooler spooler, UserState userState) {
|
RemotePrintSpooler spooler, PrintServiceCallbacks callbacks) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mUserState = userState;
|
mCallbacks = callbacks;
|
||||||
mComponentName = componentName;
|
mComponentName = componentName;
|
||||||
mIntent = new Intent().setComponent(mComponentName);
|
mIntent = new Intent().setComponent(mComponentName);
|
||||||
mUserId = userId;
|
mUserId = userId;
|
||||||
@@ -99,15 +105,42 @@ final class RemotePrintService implements DeathRecipient {
|
|||||||
mPrintServiceClient = new RemotePrintServiceClient(this);
|
mPrintServiceClient = new RemotePrintServiceClient(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ComponentName getComponentName() {
|
||||||
|
return mComponentName;
|
||||||
|
}
|
||||||
|
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
mHandler.sendEmptyMessage(MyHandler.MSG_DESTROY);
|
mHandler.sendEmptyMessage(MyHandler.MSG_DESTROY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleDestroy() {
|
private void handleDestroy() {
|
||||||
throwIfDestroyed();
|
throwIfDestroyed();
|
||||||
|
|
||||||
|
// Stop tracking printers.
|
||||||
|
if (mTrackedPrinterList != null) {
|
||||||
|
final int trackedPrinterCount = mTrackedPrinterList.size();
|
||||||
|
for (int i = 0; i < trackedPrinterCount; i++) {
|
||||||
|
PrinterId printerId = mTrackedPrinterList.get(i);
|
||||||
|
if (printerId.getServiceName().equals(mComponentName)) {
|
||||||
|
handleStopPrinterStateTracking(printerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop printer discovery.
|
||||||
|
if (mDiscoveryPriorityList != null) {
|
||||||
|
handleStopPrinterDiscovery();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy the discovery session.
|
||||||
|
if (mHasPrinterDiscoverySession) {
|
||||||
|
handleDestroyPrinterDiscoverySession();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unbind.
|
||||||
ensureUnbound();
|
ensureUnbound();
|
||||||
mAllPrintJobsHandled = false;
|
|
||||||
mHasPrinterDiscoverySession = false;
|
// Done
|
||||||
mDestroyed = true;
|
mDestroyed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,21 +154,9 @@ final class RemotePrintService implements DeathRecipient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleBinderDied() {
|
private void handleBinderDied() {
|
||||||
mAllPrintJobsHandled = false;
|
mPrintService.asBinder().unlinkToDeath(this, 0);
|
||||||
mHasPrinterDiscoverySession = false;
|
mPrintService = null;
|
||||||
mPendingCommands.clear();
|
mCallbacks.onServiceDied(this);
|
||||||
ensureUnbound();
|
|
||||||
|
|
||||||
// Makes sure all active print jobs are failed since the service
|
|
||||||
// just died. Do this off the main thread since we do to allow
|
|
||||||
// calls into the spooler on the main thread.
|
|
||||||
new AsyncTask<Void, Void, Void>() {
|
|
||||||
@Override
|
|
||||||
protected Void doInBackground(Void... params) {
|
|
||||||
failAllActivePrintJobs();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dump(PrintWriter pw, String prefix) {
|
public void dump(PrintWriter pw, String prefix) {
|
||||||
@@ -148,32 +169,17 @@ final class RemotePrintService implements DeathRecipient {
|
|||||||
pw.append(prefix).append(tab).append("bound=")
|
pw.append(prefix).append(tab).append("bound=")
|
||||||
.append(String.valueOf(isBound())).println();
|
.append(String.valueOf(isBound())).println();
|
||||||
pw.append(prefix).append(tab).append("hasDicoverySession=")
|
pw.append(prefix).append(tab).append("hasDicoverySession=")
|
||||||
.append(String.valueOf(mHasPrinterDiscoverySession));
|
.append(String.valueOf(mHasPrinterDiscoverySession)).println();
|
||||||
}
|
pw.append(prefix).append(tab).append("isDiscoveringPrinters=")
|
||||||
|
.append(String.valueOf(mDiscoveryPriorityList != null)).println();
|
||||||
private void failAllActivePrintJobs() {
|
pw.append(prefix).append(tab).append("trackedPrinters=")
|
||||||
List<PrintJobInfo> printJobs = mSpooler.getPrintJobInfos(mComponentName,
|
.append((mTrackedPrinterList != null) ? mTrackedPrinterList.toString() : "null");
|
||||||
PrintJobInfo.STATE_ANY_ACTIVE, PrintManager.APP_ID_ANY);
|
|
||||||
if (printJobs == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final long identity = Binder.clearCallingIdentity();
|
|
||||||
try {
|
|
||||||
final int printJobCount = printJobs.size();
|
|
||||||
for (int i = 0; i < printJobCount; i++) {
|
|
||||||
PrintJobInfo printJob = printJobs.get(i);
|
|
||||||
mSpooler.setPrintJobState(printJob.getId(), PrintJobInfo.STATE_FAILED,
|
|
||||||
mContext.getString(R.string.reason_unknown));
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
Binder.restoreCallingIdentity(identity);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleOnAllPrintJobsHandled() {
|
private void handleOnAllPrintJobsHandled() {
|
||||||
throwIfDestroyed();
|
throwIfDestroyed();
|
||||||
|
|
||||||
mAllPrintJobsHandled = true;
|
mHasActivePrintJobs = false;
|
||||||
|
|
||||||
if (isBound()) {
|
if (isBound()) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
@@ -217,7 +223,7 @@ final class RemotePrintService implements DeathRecipient {
|
|||||||
private void handleOnPrintJobQueued(final PrintJobInfo printJob) {
|
private void handleOnPrintJobQueued(final PrintJobInfo printJob) {
|
||||||
throwIfDestroyed();
|
throwIfDestroyed();
|
||||||
|
|
||||||
mAllPrintJobsHandled = false;
|
mHasActivePrintJobs = true;
|
||||||
|
|
||||||
if (!isBound()) {
|
if (!isBound()) {
|
||||||
ensureBound();
|
ensureBound();
|
||||||
@@ -296,7 +302,7 @@ final class RemotePrintService implements DeathRecipient {
|
|||||||
|
|
||||||
// If the service has no print jobs and no active discovery
|
// If the service has no print jobs and no active discovery
|
||||||
// session anymore we should disconnect from it.
|
// session anymore we should disconnect from it.
|
||||||
if (mAllPrintJobsHandled) {
|
if (!mHasActivePrintJobs) {
|
||||||
ensureUnbound();
|
ensureUnbound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -326,6 +332,11 @@ final class RemotePrintService implements DeathRecipient {
|
|||||||
} catch (RemoteException re) {
|
} catch (RemoteException re) {
|
||||||
Slog.e(LOG_TAG, "Error starting printer dicovery.", re);
|
Slog.e(LOG_TAG, "Error starting printer dicovery.", re);
|
||||||
}
|
}
|
||||||
|
// Take a note that we are doing discovery.
|
||||||
|
mDiscoveryPriorityList = new ArrayList<PrinterId>();
|
||||||
|
if (priorityList != null) {
|
||||||
|
mDiscoveryPriorityList.addAll(priorityList);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,6 +358,8 @@ final class RemotePrintService implements DeathRecipient {
|
|||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.i(LOG_TAG, "[user: " + mUserId + "] stopPrinterDiscovery()");
|
Slog.i(LOG_TAG, "[user: " + mUserId + "] stopPrinterDiscovery()");
|
||||||
}
|
}
|
||||||
|
// We are not doing discovery anymore.
|
||||||
|
mDiscoveryPriorityList = null;
|
||||||
try {
|
try {
|
||||||
mPrintService.stopPrinterDiscovery();
|
mPrintService.stopPrinterDiscovery();
|
||||||
} catch (RemoteException re) {
|
} catch (RemoteException re) {
|
||||||
@@ -406,6 +419,11 @@ final class RemotePrintService implements DeathRecipient {
|
|||||||
} catch (RemoteException re) {
|
} catch (RemoteException re) {
|
||||||
Slog.e(LOG_TAG, "Error requesting start printer tracking.", re);
|
Slog.e(LOG_TAG, "Error requesting start printer tracking.", re);
|
||||||
}
|
}
|
||||||
|
// Take a note we are tracking the printer.
|
||||||
|
if (mTrackedPrinterList == null) {
|
||||||
|
mTrackedPrinterList = new ArrayList<PrinterId>();
|
||||||
|
}
|
||||||
|
mTrackedPrinterList.add(printerId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,6 +446,11 @@ final class RemotePrintService implements DeathRecipient {
|
|||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.i(LOG_TAG, "[user: " + mUserId + "] stopPrinterTracking()");
|
Slog.i(LOG_TAG, "[user: " + mUserId + "] stopPrinterTracking()");
|
||||||
}
|
}
|
||||||
|
// We are no longer tracking the printer.
|
||||||
|
mTrackedPrinterList.remove(printerId);
|
||||||
|
if (mTrackedPrinterList.isEmpty()) {
|
||||||
|
mTrackedPrinterList = null;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
mPrintService.stopPrinterStateTracking(printerId);
|
mPrintService.stopPrinterStateTracking(printerId);
|
||||||
} catch (RemoteException re) {
|
} catch (RemoteException re) {
|
||||||
@@ -461,6 +484,10 @@ final class RemotePrintService implements DeathRecipient {
|
|||||||
}
|
}
|
||||||
mBinding = false;
|
mBinding = false;
|
||||||
mPendingCommands.clear();
|
mPendingCommands.clear();
|
||||||
|
mHasActivePrintJobs = false;
|
||||||
|
mHasPrinterDiscoverySession = false;
|
||||||
|
mDiscoveryPriorityList = null;
|
||||||
|
mTrackedPrinterList = null;
|
||||||
if (isBound()) {
|
if (isBound()) {
|
||||||
try {
|
try {
|
||||||
mPrintService.setClient(null);
|
mPrintService.setClient(null);
|
||||||
@@ -500,11 +527,31 @@ final class RemotePrintService implements DeathRecipient {
|
|||||||
handleBinderDied();
|
handleBinderDied();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// If there is a session, then the service died after creating
|
||||||
|
// a session. Hence, recreate the session.
|
||||||
|
if (mHasPrinterDiscoverySession) {
|
||||||
|
handleCreatePrinterDiscoverySession();
|
||||||
|
}
|
||||||
|
// If there is a priority list, then the service died during
|
||||||
|
// discovery and is restarted. Hence, start discovery.
|
||||||
|
if (mDiscoveryPriorityList != null) {
|
||||||
|
handleStartPrinterDiscovery(mDiscoveryPriorityList);
|
||||||
|
}
|
||||||
|
// If there is a tracked printer list, then the service died
|
||||||
|
// during discovery and is restarted. Hence, start tracking.
|
||||||
|
if (mTrackedPrinterList != null) {
|
||||||
|
final int trackedPrinterCount = mTrackedPrinterList.size();
|
||||||
|
for (int i = 0; i < trackedPrinterCount; i++) {
|
||||||
|
handleStartPrinterStateTracking(mTrackedPrinterList.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Finally, do all the pending work.
|
||||||
final int pendingCommandCount = mPendingCommands.size();
|
final int pendingCommandCount = mPendingCommands.size();
|
||||||
for (int i = 0; i < pendingCommandCount; i++) {
|
for (int i = 0; i < pendingCommandCount; i++) {
|
||||||
Runnable pendingCommand = mPendingCommands.get(i);
|
Runnable pendingCommand = mPendingCommands.get(i);
|
||||||
pendingCommand.run();
|
pendingCommand.run();
|
||||||
}
|
}
|
||||||
|
mPendingCommands.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -677,7 +724,7 @@ final class RemotePrintService implements DeathRecipient {
|
|||||||
throwIfPrinterIdsForPrinterInfoTampered(service.mComponentName, printers);
|
throwIfPrinterIdsForPrinterInfoTampered(service.mComponentName, printers);
|
||||||
final long identity = Binder.clearCallingIdentity();
|
final long identity = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
service.mUserState.onPrintersAdded(printers);
|
service.mCallbacks.onPrintersAdded(printers);
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(identity);
|
Binder.restoreCallingIdentity(identity);
|
||||||
}
|
}
|
||||||
@@ -691,7 +738,7 @@ final class RemotePrintService implements DeathRecipient {
|
|||||||
throwIfPrinterIdsTampered(service.mComponentName, printerIds);
|
throwIfPrinterIdsTampered(service.mComponentName, printerIds);
|
||||||
final long identity = Binder.clearCallingIdentity();
|
final long identity = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
service.mUserState.onPrintersRemoved(printerIds);
|
service.mCallbacks.onPrintersRemoved(printerIds);
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(identity);
|
Binder.restoreCallingIdentity(identity);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
@@ -57,7 +56,7 @@ final class RemotePrintSpooler {
|
|||||||
|
|
||||||
private static final String LOG_TAG = "RemotePrintSpooler";
|
private static final String LOG_TAG = "RemotePrintSpooler";
|
||||||
|
|
||||||
private static final boolean DEBUG = true && Build.IS_DEBUGGABLE;
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
private static final long BIND_SPOOLER_SERVICE_TIMEOUT = 10000;
|
private static final long BIND_SPOOLER_SERVICE_TIMEOUT = 10000;
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ import android.content.pm.ApplicationInfo;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
import android.content.pm.ServiceInfo;
|
import android.content.pm.ServiceInfo;
|
||||||
import android.os.Build;
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Binder;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
@@ -32,6 +33,7 @@ import android.os.RemoteCallbackList;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.print.IPrinterDiscoveryObserver;
|
import android.print.IPrinterDiscoveryObserver;
|
||||||
import android.print.PrintJobInfo;
|
import android.print.PrintJobInfo;
|
||||||
|
import android.print.PrintManager;
|
||||||
import android.print.PrinterId;
|
import android.print.PrinterId;
|
||||||
import android.print.PrinterInfo;
|
import android.print.PrinterInfo;
|
||||||
import android.printservice.PrintServiceInfo;
|
import android.printservice.PrintServiceInfo;
|
||||||
@@ -43,7 +45,9 @@ import android.util.ArraySet;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
|
import com.android.internal.R;
|
||||||
import com.android.internal.os.SomeArgs;
|
import com.android.internal.os.SomeArgs;
|
||||||
|
import com.android.server.print.RemotePrintService.PrintServiceCallbacks;
|
||||||
import com.android.server.print.RemotePrintSpooler.PrintSpoolerCallbacks;
|
import com.android.server.print.RemotePrintSpooler.PrintSpoolerCallbacks;
|
||||||
|
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
@@ -58,11 +62,11 @@ import java.util.Set;
|
|||||||
/**
|
/**
|
||||||
* Represents the print state for a user.
|
* Represents the print state for a user.
|
||||||
*/
|
*/
|
||||||
final class UserState implements PrintSpoolerCallbacks {
|
final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks {
|
||||||
|
|
||||||
private static final String LOG_TAG = "UserState";
|
private static final String LOG_TAG = "UserState";
|
||||||
|
|
||||||
private static final boolean DEBUG = true && Build.IS_DEBUGGABLE;
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
private static final int MAX_ITEMS_PER_CALLBACK = 50;
|
private static final int MAX_ITEMS_PER_CALLBACK = 50;
|
||||||
|
|
||||||
@@ -246,6 +250,7 @@ final class UserState implements PrintSpoolerCallbacks {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onPrintersAdded(List<PrinterInfo> printers) {
|
public void onPrintersAdded(List<PrinterInfo> printers) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
throwIfDestroyedLocked();
|
throwIfDestroyedLocked();
|
||||||
@@ -257,11 +262,11 @@ final class UserState implements PrintSpoolerCallbacks {
|
|||||||
if (mPrinterDiscoverySession == null) {
|
if (mPrinterDiscoverySession == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Request an updated.
|
|
||||||
mPrinterDiscoverySession.onPrintersAddedLocked(printers);
|
mPrinterDiscoverySession.onPrintersAddedLocked(printers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onPrintersRemoved(List<PrinterId> printerIds) {
|
public void onPrintersRemoved(List<PrinterId> printerIds) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
throwIfDestroyedLocked();
|
throwIfDestroyedLocked();
|
||||||
@@ -273,11 +278,28 @@ final class UserState implements PrintSpoolerCallbacks {
|
|||||||
if (mPrinterDiscoverySession == null) {
|
if (mPrinterDiscoverySession == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Request an updated.
|
|
||||||
mPrinterDiscoverySession.onPrintersRemovedLocked(printerIds);
|
mPrinterDiscoverySession.onPrintersRemovedLocked(printerIds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceDied(RemotePrintService service) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
throwIfDestroyedLocked();
|
||||||
|
// No services - nothing to do.
|
||||||
|
if (mActiveServices.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Fail all print jobs.
|
||||||
|
failActivePrintJobsForService(service.getComponentName());
|
||||||
|
// No session - nothing to do.
|
||||||
|
if (mPrinterDiscoverySession == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mPrinterDiscoverySession.onServiceDiedLocked(service);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void updateIfNeededLocked() {
|
public void updateIfNeededLocked() {
|
||||||
throwIfDestroyedLocked();
|
throwIfDestroyedLocked();
|
||||||
if (readConfigurationLocked()) {
|
if (readConfigurationLocked()) {
|
||||||
@@ -516,23 +538,72 @@ final class UserState implements PrintSpoolerCallbacks {
|
|||||||
if (!mActiveServices.containsKey(serviceName)) {
|
if (!mActiveServices.containsKey(serviceName)) {
|
||||||
RemotePrintService service = new RemotePrintService(
|
RemotePrintService service = new RemotePrintService(
|
||||||
mContext, serviceName, mUserId, mSpooler, this);
|
mContext, serviceName, mUserId, mSpooler, this);
|
||||||
mActiveServices.put(serviceName, service);
|
addServiceLocked(service);
|
||||||
if (mPrinterDiscoverySession != null) {
|
|
||||||
mPrinterDiscoverySession.onServiceAddedLocked(service);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
RemotePrintService service = mActiveServices.remove(serviceName);
|
RemotePrintService service = mActiveServices.remove(serviceName);
|
||||||
if (service != null) {
|
if (service != null) {
|
||||||
service.destroy();
|
removeServiceLocked(service);
|
||||||
if (mPrinterDiscoverySession != null) {
|
|
||||||
mPrinterDiscoverySession.onServiceRemovedLocked(serviceName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addServiceLocked(RemotePrintService service) {
|
||||||
|
mActiveServices.put(service.getComponentName(), service);
|
||||||
|
if (mPrinterDiscoverySession != null) {
|
||||||
|
mPrinterDiscoverySession.onServiceAddedLocked(service);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeServiceLocked(RemotePrintService service) {
|
||||||
|
// Fail all print jobs.
|
||||||
|
failActivePrintJobsForService(service.getComponentName());
|
||||||
|
// If discovery is in progress, tear down the service.
|
||||||
|
if (mPrinterDiscoverySession != null) {
|
||||||
|
mPrinterDiscoverySession.onServiceRemovedLocked(service);
|
||||||
|
} else {
|
||||||
|
// Otherwise, just destroy it.
|
||||||
|
service.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void failActivePrintJobsForService(final ComponentName serviceName) {
|
||||||
|
// Makes sure all active print jobs are failed since the service
|
||||||
|
// 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>() {
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
failActivePrintJobsForServiceInternal(serviceName);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
|
||||||
|
} else {
|
||||||
|
failActivePrintJobsForServiceInternal(serviceName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void failActivePrintJobsForServiceInternal(ComponentName serviceName) {
|
||||||
|
List<PrintJobInfo> printJobs = mSpooler.getPrintJobInfos(serviceName,
|
||||||
|
PrintJobInfo.STATE_ANY_ACTIVE, PrintManager.APP_ID_ANY);
|
||||||
|
if (printJobs == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final long identity = Binder.clearCallingIdentity();
|
||||||
|
try {
|
||||||
|
final int printJobCount = printJobs.size();
|
||||||
|
for (int i = 0; i < printJobCount; i++) {
|
||||||
|
PrintJobInfo printJob = printJobs.get(i);
|
||||||
|
mSpooler.setPrintJobState(printJob.getId(), PrintJobInfo.STATE_FAILED,
|
||||||
|
mContext.getString(R.string.reason_unknown));
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void throwIfDestroyedLocked() {
|
private void throwIfDestroyedLocked() {
|
||||||
if (mDestroyed) {
|
if (mDestroyed) {
|
||||||
throw new IllegalStateException("Cannot interact with a destroyed instance.");
|
throw new IllegalStateException("Cannot interact with a destroyed instance.");
|
||||||
@@ -603,17 +674,18 @@ final class UserState implements PrintSpoolerCallbacks {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If printer discovery is ongoing and the start request has a list
|
final boolean discoveryStarted = !mStartedPrinterDiscoveryTokens.isEmpty();
|
||||||
// of printer to be checked, then we just request validating them.
|
|
||||||
if (!mStartedPrinterDiscoveryTokens.isEmpty()
|
|
||||||
&& priorityList != null && !priorityList.isEmpty()) {
|
|
||||||
validatePrinters(priorityList);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remember we got a start request to match with an end.
|
// Remember we got a start request to match with an end.
|
||||||
mStartedPrinterDiscoveryTokens.add(observer.asBinder());
|
mStartedPrinterDiscoveryTokens.add(observer.asBinder());
|
||||||
|
|
||||||
|
// If printer discovery is ongoing and the start request has a list
|
||||||
|
// of printer to be checked, then we just request validating them.
|
||||||
|
if (discoveryStarted && priorityList != null && !priorityList.isEmpty()) {
|
||||||
|
validatePrinters(priorityList);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// The service are already performing discovery - nothing to do.
|
// The service are already performing discovery - nothing to do.
|
||||||
if (mStartedPrinterDiscoveryTokens.size() > 1) {
|
if (mStartedPrinterDiscoveryTokens.size() > 1) {
|
||||||
return;
|
return;
|
||||||
@@ -822,32 +894,20 @@ final class UserState implements PrintSpoolerCallbacks {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onServiceRemovedLocked(ComponentName serviceName) {
|
public void onServiceRemovedLocked(RemotePrintService service) {
|
||||||
if (mIsDestroyed) {
|
if (mIsDestroyed) {
|
||||||
Log.w(LOG_TAG, "Not updating removed service - session destroyed");
|
Log.w(LOG_TAG, "Not updating removed service - session destroyed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// No printers - nothing to do.
|
// Remove the reported and tracked printers for that service.
|
||||||
if (mPrinters.isEmpty()) {
|
ComponentName serviceName = service.getComponentName();
|
||||||
return;
|
removePrintersForServiceLocked(serviceName);
|
||||||
}
|
service.destroy();
|
||||||
// Remove the printers for that service.
|
}
|
||||||
List<PrinterId> removedPrinterIds = null;
|
|
||||||
final int printerCount = mPrinters.size();
|
public void onServiceDiedLocked(RemotePrintService service) {
|
||||||
for (int i = 0; i < printerCount; i++) {
|
// Remove the reported by that service.
|
||||||
PrinterId printerId = mPrinters.keyAt(i);
|
removePrintersForServiceLocked(service.getComponentName());
|
||||||
if (printerId.getServiceName().equals(serviceName)) {
|
|
||||||
if (removedPrinterIds == null) {
|
|
||||||
removedPrinterIds = new ArrayList<PrinterId>();
|
|
||||||
}
|
|
||||||
removedPrinterIds.add(printerId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!removedPrinterIds.isEmpty()) {
|
|
||||||
mHandler.obtainMessage(
|
|
||||||
SessionHandler.MSG_DISPATCH_PRINTERS_REMOVED,
|
|
||||||
removedPrinterIds).sendToTarget();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onServiceAddedLocked(RemotePrintService service) {
|
public void onServiceAddedLocked(RemotePrintService service) {
|
||||||
@@ -908,6 +968,34 @@ final class UserState implements PrintSpoolerCallbacks {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void removePrintersForServiceLocked(ComponentName serviceName) {
|
||||||
|
// No printers - nothing to do.
|
||||||
|
if (mPrinters.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Remove the printers for that service.
|
||||||
|
List<PrinterId> removedPrinterIds = null;
|
||||||
|
final int printerCount = mPrinters.size();
|
||||||
|
for (int i = 0; i < printerCount; i++) {
|
||||||
|
PrinterId printerId = mPrinters.keyAt(i);
|
||||||
|
if (printerId.getServiceName().equals(serviceName)) {
|
||||||
|
if (removedPrinterIds == null) {
|
||||||
|
removedPrinterIds = new ArrayList<PrinterId>();
|
||||||
|
}
|
||||||
|
removedPrinterIds.add(printerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final int removedPrinterCount = removedPrinterIds.size();
|
||||||
|
for (int i = 0; i < removedPrinterCount; i++) {
|
||||||
|
mPrinters.remove(removedPrinterIds.get(i));
|
||||||
|
}
|
||||||
|
if (removedPrinterIds != null) {
|
||||||
|
mHandler.obtainMessage(
|
||||||
|
SessionHandler.MSG_DISPATCH_PRINTERS_REMOVED,
|
||||||
|
removedPrinterIds).sendToTarget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void handleDispatchPrintersAdded(List<PrinterInfo> addedPrinters) {
|
private void handleDispatchPrintersAdded(List<PrinterInfo> addedPrinters) {
|
||||||
final int observerCount = mDiscoveryObservers.beginBroadcast();
|
final int observerCount = mDiscoveryObservers.beginBroadcast();
|
||||||
for (int i = 0; i < observerCount; i++) {
|
for (int i = 0; i < observerCount; i++) {
|
||||||
@@ -1026,14 +1114,17 @@ final class UserState implements PrintSpoolerCallbacks {
|
|||||||
public static final int MSG_DISPATCH_PRINTERS_REMOVED = 4;
|
public static final int MSG_DISPATCH_PRINTERS_REMOVED = 4;
|
||||||
|
|
||||||
public static final int MSG_CREATE_PRINTER_DISCOVERY_SESSION = 5;
|
public static final int MSG_CREATE_PRINTER_DISCOVERY_SESSION = 5;
|
||||||
public static final int MSG_START_PRINTER_DISCOVERY = 6;
|
public static final int MSG_DESTROY_PRINTER_DISCOVERY_SESSION = 6;
|
||||||
public static final int MSG_DISPATCH_CREATE_PRINTER_DISCOVERY_SESSION = 7;
|
public static final int MSG_START_PRINTER_DISCOVERY = 7;
|
||||||
public static final int MSG_DISPATCH_DESTROY_PRINTER_DISCOVERY_SESSION = 8;
|
public static final int MSG_STOP_PRINTER_DISCOVERY = 8;
|
||||||
public static final int MSG_DISPATCH_START_PRINTER_DISCOVERY = 9;
|
public static final int MSG_DISPATCH_CREATE_PRINTER_DISCOVERY_SESSION = 9;
|
||||||
public static final int MSG_DISPATCH_STOP_PRINTER_DISCOVERY = 10;
|
public static final int MSG_DISPATCH_DESTROY_PRINTER_DISCOVERY_SESSION = 10;
|
||||||
public static final int MSG_VALIDATE_PRINTERS = 11;
|
public static final int MSG_DISPATCH_START_PRINTER_DISCOVERY = 11;
|
||||||
public static final int MSG_START_PRINTER_STATE_TRACKING = 12;
|
public static final int MSG_DISPATCH_STOP_PRINTER_DISCOVERY = 12;
|
||||||
public static final int MSG_STOP_PRINTER_STATE_TRACKING = 13;
|
public static final int MSG_VALIDATE_PRINTERS = 13;
|
||||||
|
public static final int MSG_START_PRINTER_STATE_TRACKING = 14;
|
||||||
|
public static final int MSG_STOP_PRINTER_STATE_TRACKING = 15;
|
||||||
|
public static final int MSG_DESTROY_SERVICE = 16;
|
||||||
|
|
||||||
SessionHandler(Looper looper) {
|
SessionHandler(Looper looper) {
|
||||||
super(looper, null, false);
|
super(looper, null, false);
|
||||||
@@ -1074,11 +1165,21 @@ final class UserState implements PrintSpoolerCallbacks {
|
|||||||
service.createPrinterDiscoverySession();
|
service.createPrinterDiscoverySession();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case MSG_DESTROY_PRINTER_DISCOVERY_SESSION: {
|
||||||
|
RemotePrintService service = (RemotePrintService) message.obj;
|
||||||
|
service.destroyPrinterDiscoverySession();
|
||||||
|
} break;
|
||||||
|
|
||||||
case MSG_START_PRINTER_DISCOVERY: {
|
case MSG_START_PRINTER_DISCOVERY: {
|
||||||
RemotePrintService service = (RemotePrintService) message.obj;
|
RemotePrintService service = (RemotePrintService) message.obj;
|
||||||
service.startPrinterDiscovery(null);
|
service.startPrinterDiscovery(null);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case MSG_STOP_PRINTER_DISCOVERY: {
|
||||||
|
RemotePrintService service = (RemotePrintService) message.obj;
|
||||||
|
service.stopPrinterDiscovery();
|
||||||
|
} break;
|
||||||
|
|
||||||
case MSG_DISPATCH_CREATE_PRINTER_DISCOVERY_SESSION: {
|
case MSG_DISPATCH_CREATE_PRINTER_DISCOVERY_SESSION: {
|
||||||
List<RemotePrintService> services = (List<RemotePrintService>) message.obj;
|
List<RemotePrintService> services = (List<RemotePrintService>) message.obj;
|
||||||
handleDispatchCreatePrinterDiscoverySession(services);
|
handleDispatchCreatePrinterDiscoverySession(services);
|
||||||
@@ -1124,7 +1225,12 @@ final class UserState implements PrintSpoolerCallbacks {
|
|||||||
PrinterId printerId = (PrinterId) args.arg2;
|
PrinterId printerId = (PrinterId) args.arg2;
|
||||||
args.recycle();
|
args.recycle();
|
||||||
handleStopPrinterStateTracking(service, printerId);
|
handleStopPrinterStateTracking(service, printerId);
|
||||||
}
|
} break;
|
||||||
|
|
||||||
|
case MSG_DESTROY_SERVICE: {
|
||||||
|
RemotePrintService service = (RemotePrintService) message.obj;
|
||||||
|
service.destroy();
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user