summaryrefslogtreecommitdiffstats
path: root/services/java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java')
-rw-r--r--services/java/com/android/server/print/PrintManagerService.java40
-rw-r--r--services/java/com/android/server/print/RemotePrintService.java129
-rw-r--r--services/java/com/android/server/print/UserState.java226
3 files changed, 354 insertions, 41 deletions
diff --git a/services/java/com/android/server/print/PrintManagerService.java b/services/java/com/android/server/print/PrintManagerService.java
index 671a5dc..2563b58 100644
--- a/services/java/com/android/server/print/PrintManagerService.java
+++ b/services/java/com/android/server/print/PrintManagerService.java
@@ -254,7 +254,7 @@ public final class PrintManagerService extends IPrintManager.Stub {
}
@Override
- public void requestPrinterUpdate(PrinterId printerId, int userId) {
+ public void validatePrinters(List<PrinterId> printerIds, int userId) {
final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
final UserState userState;
synchronized (mLock) {
@@ -262,7 +262,37 @@ public final class PrintManagerService extends IPrintManager.Stub {
}
final long identity = Binder.clearCallingIdentity();
try {
- userState.requestPrinterUpdate(printerId);
+ userState.validatePrinters(printerIds);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void startPrinterStateTracking(PrinterId printerId, int userId) {
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ userState.startPrinterStateTracking(printerId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void stopPrinterStateTracking(PrinterId printerId, int userId) {
+ final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
+ final UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(resolvedUserId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ userState.stopPrinterStateTracking(printerId);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -432,10 +462,12 @@ public final class PrintManagerService extends IPrintManager.Stub {
if (appId == callingAppId) {
return appId;
}
- if (mContext.checkCallingPermission(Manifest.permission.ACCESS_ALL_PRINT_JOBS)
+ if (mContext.checkCallingPermission(
+ "com.android.printspooler.permission.ACCESS_ALL_PRINT_JOBS")
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Call from app " + callingAppId + " as app "
- + appId + " without permission ACCESS_ALL_PRINT_JOBS");
+ + appId + " without com.android.printspooler.permission"
+ + ".ACCESS_ALL_PRINT_JOBS");
}
return appId;
}
diff --git a/services/java/com/android/server/print/RemotePrintService.java b/services/java/com/android/server/print/RemotePrintService.java
index 7f4b343..14af9d8 100644
--- a/services/java/com/android/server/print/RemotePrintService.java
+++ b/services/java/com/android/server/print/RemotePrintService.java
@@ -25,6 +25,7 @@ import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
+import android.os.AsyncTask;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
@@ -38,6 +39,8 @@ import android.printservice.IPrintService;
import android.printservice.IPrintServiceClient;
import android.util.Slog;
+import com.android.internal.R;
+
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
@@ -121,6 +124,36 @@ final class RemotePrintService implements DeathRecipient {
mHasPrinterDiscoverySession = false;
mPendingCommands.clear();
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);
+ }
+
+ private void failAllActivePrintJobs() {
+ List<PrintJobInfo> printJobs = mSpooler.getPrintJobInfos(mComponentName,
+ 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() {
@@ -308,29 +341,83 @@ final class RemotePrintService implements DeathRecipient {
}
}
- public void requestPrinterUpdate(PrinterId printerId) {
- mHandler.obtainMessage(MyHandler.MSG_REQUEST_PRINTER_UPDATE,
+ public void validatePrinters(List<PrinterId> printerIds) {
+ mHandler.obtainMessage(MyHandler.MSG_VALIDATE_PRINTERS,
+ printerIds).sendToTarget();
+ }
+
+ private void handleValidatePrinters(final List<PrinterId> printerIds) {
+ throwIfDestroyed();
+ if (!isBound()) {
+ ensureBound();
+ mPendingCommands.add(new Runnable() {
+ @Override
+ public void run() {
+ handleValidatePrinters(printerIds);
+ }
+ });
+ } else {
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "[user: " + mUserId + "] handleValidatePrinters()");
+ }
+ try {
+ mPrintService.validatePrinters(printerIds);
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Error requesting printers validation.", re);
+ }
+ }
+ }
+
+ public void startPrinterStateTracking(PrinterId printerId) {
+ mHandler.obtainMessage(MyHandler.MSG_START_PRINTER_STATE_TRACKING,
+ printerId).sendToTarget();
+ }
+
+ private void handleStartPrinterStateTracking(final PrinterId printerId) {
+ throwIfDestroyed();
+ if (!isBound()) {
+ ensureBound();
+ mPendingCommands.add(new Runnable() {
+ @Override
+ public void run() {
+ handleStartPrinterStateTracking(printerId);
+ }
+ });
+ } else {
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "[user: " + mUserId + "] handleStartPrinterTracking()");
+ }
+ try {
+ mPrintService.startPrinterStateTracking(printerId);
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Error requesting start printer tracking.", re);
+ }
+ }
+ }
+
+ public void stopPrinterStateTracking(PrinterId printerId) {
+ mHandler.obtainMessage(MyHandler.MSG_STOP_PRINTER_STATE_TRACKING,
printerId).sendToTarget();
}
- private void handleRequestPrinterUpdate(final PrinterId printerId) {
+ private void handleStopPrinterStateTracking(final PrinterId printerId) {
throwIfDestroyed();
if (!isBound()) {
ensureBound();
mPendingCommands.add(new Runnable() {
@Override
public void run() {
- handleRequestPrinterUpdate(printerId);
+ handleStopPrinterStateTracking(printerId);
}
});
} else {
if (DEBUG) {
- Slog.i(LOG_TAG, "[user: " + mUserId + "] requestPrinterUpdate()");
+ Slog.i(LOG_TAG, "[user: " + mUserId + "] handleStopPrinterTracking()");
}
try {
- mPrintService.requestPrinterUpdate(printerId);
+ mPrintService.stopPrinterStateTracking(printerId);
} catch (RemoteException re) {
- Slog.e(LOG_TAG, "Error requesting a printer update.", re);
+ Slog.e(LOG_TAG, "Error requesting stop printer tracking.", re);
}
}
}
@@ -417,12 +504,14 @@ final class RemotePrintService implements DeathRecipient {
public static final int MSG_DESTROY_PRINTER_DISCOVERY_SESSION = 2;
public static final int MSG_START_PRINTER_DISCOVERY = 3;
public static final int MSG_STOP_PRINTER_DISCOVERY = 4;
- public static final int MSG_REQUEST_PRINTER_UPDATE = 5;
- public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 6;
- public static final int MSG_ON_REQUEST_CANCEL_PRINT_JOB = 7;
- public static final int MSG_ON_PRINT_JOB_QUEUED = 8;
- public static final int MSG_DESTROY = 9;
- public static final int MSG_BINDER_DIED = 10;
+ public static final int MSG_VALIDATE_PRINTERS = 5;
+ public static final int MSG_START_PRINTER_STATE_TRACKING = 6;
+ public static final int MSG_STOP_PRINTER_STATE_TRACKING = 7;
+ public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 8;
+ public static final int MSG_ON_REQUEST_CANCEL_PRINT_JOB = 9;
+ public static final int MSG_ON_PRINT_JOB_QUEUED = 10;
+ public static final int MSG_DESTROY = 11;
+ public static final int MSG_BINDER_DIED = 12;
public MyHandler(Looper looper) {
super(looper, null, false);
@@ -449,9 +538,19 @@ final class RemotePrintService implements DeathRecipient {
handleStopPrinterDiscovery();
} break;
- case MSG_REQUEST_PRINTER_UPDATE: {
+ case MSG_VALIDATE_PRINTERS: {
+ List<PrinterId> printerIds = (List<PrinterId>) message.obj;
+ handleValidatePrinters(printerIds);
+ } break;
+
+ case MSG_START_PRINTER_STATE_TRACKING: {
+ PrinterId printerId = (PrinterId) message.obj;
+ handleStartPrinterStateTracking(printerId);
+ } break;
+
+ case MSG_STOP_PRINTER_STATE_TRACKING: {
PrinterId printerId = (PrinterId) message.obj;
- handleRequestPrinterUpdate(printerId);
+ handleStopPrinterStateTracking(printerId);
} break;
case MSG_ON_ALL_PRINT_JOBS_HANDLED: {
diff --git a/services/java/com/android/server/print/UserState.java b/services/java/com/android/server/print/UserState.java
index c979a11..4a1b96b 100644
--- a/services/java/com/android/server/print/UserState.java
+++ b/services/java/com/android/server/print/UserState.java
@@ -19,8 +19,12 @@ package com.android.server.print;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
@@ -46,6 +50,7 @@ import com.android.server.print.RemotePrintSpooler.PrintSpoolerCallbacks;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -63,6 +68,11 @@ final class UserState implements PrintSpoolerCallbacks {
private static final char COMPONENT_NAME_SEPARATOR = ':';
+ private static final String SHARED_PREFERENCES_FILE = "shared_prefs";
+
+ private static final String KEY_SYSTEM_PRINT_SERVICES_ENABLED =
+ "KEY_SYSTEM_PRINT_SERVICES_ENABLED";
+
private final SimpleStringSplitter mStringColonSplitter =
new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
@@ -95,6 +105,7 @@ final class UserState implements PrintSpoolerCallbacks {
mUserId = userId;
mLock = lock;
mSpooler = new RemotePrintSpooler(context, userId, this);
+ enableSystemPrintServicesOnce();
}
@Override
@@ -190,7 +201,7 @@ final class UserState implements PrintSpoolerCallbacks {
}
}
- public void requestPrinterUpdate(PrinterId printerId) {
+ public void validatePrinters(List<PrinterId> printerIds) {
synchronized (mLock) {
throwIfDestroyedLocked();
// No services - nothing to do.
@@ -202,7 +213,39 @@ final class UserState implements PrintSpoolerCallbacks {
return;
}
// Request an updated.
- mPrinterDiscoverySession.requestPrinterUpdateLocked(printerId);
+ mPrinterDiscoverySession.validatePrintersLocked(printerIds);
+ }
+ }
+
+ public void startPrinterStateTracking(PrinterId printerId) {
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ // No services - nothing to do.
+ if (mActiveServices.isEmpty()) {
+ return;
+ }
+ // No session - nothing to do.
+ if (mPrinterDiscoverySession == null) {
+ return;
+ }
+ // Request start tracking the printer.
+ mPrinterDiscoverySession.startPrinterStateTrackingLocked(printerId);
+ }
+ }
+
+ public void stopPrinterStateTracking(PrinterId printerId) {
+ synchronized (mLock) {
+ throwIfDestroyedLocked();
+ // No services - nothing to do.
+ if (mActiveServices.isEmpty()) {
+ return;
+ }
+ // No session - nothing to do.
+ if (mPrinterDiscoverySession == null) {
+ return;
+ }
+ // Request stop tracking the printer.
+ mPrinterDiscoverySession.stopPrinterStateTrackingLocked(printerId);
}
}
@@ -365,6 +408,36 @@ final class UserState implements PrintSpoolerCallbacks {
return false;
}
+ private void enableSystemPrintServicesOnce() {
+ SharedPreferences preferences = mContext.getSharedPreferences(
+ SHARED_PREFERENCES_FILE, Context.MODE_PRIVATE);
+ if (preferences.getInt(KEY_SYSTEM_PRINT_SERVICES_ENABLED, 0) == 0) {
+ Editor editor = preferences.edit();
+ editor.putInt(KEY_SYSTEM_PRINT_SERVICES_ENABLED, 1);
+ editor.commit();
+
+ readInstalledPrintServicesLocked();
+
+ StringBuilder builder = new StringBuilder();
+
+ final int serviceCount = mInstalledServices.size();
+ for (int i = 0; i < serviceCount; i++) {
+ ServiceInfo serviceInfo = mInstalledServices.get(i).getResolveInfo().serviceInfo;
+ if ((serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ ComponentName serviceName = new ComponentName(
+ serviceInfo.packageName, serviceInfo.name);
+ if (builder.length() > 0) {
+ builder.append(":");
+ }
+ builder.append(serviceName.flattenToString());
+ }
+ }
+
+ Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ Settings.Secure.ENABLED_PRINT_SERVICES, builder.toString(), mUserId);
+ }
+ }
+
private void onConfigurationChangedLocked() {
final int installedCount = mInstalledServices.size();
for (int i = 0; i < installedCount; i++) {
@@ -415,6 +488,8 @@ final class UserState implements PrintSpoolerCallbacks {
private final List<IBinder> mStartedPrinterDiscoveryTokens = new ArrayList<IBinder>();
+ private final List<PrinterId> mStateTrackedPrinters = new ArrayList<PrinterId>();
+
private final Handler mHandler;
private boolean mIsDestroyed;
@@ -461,14 +536,10 @@ final class UserState implements PrintSpoolerCallbacks {
}
// If printer discovery is ongoing and the start request has a list
- // of printer to be checked, then we just request refreshing each of
- // them rather making another start discovery request.
+ // of printer to be checked, then we just request validating them.
if (!mStartedPrinterDiscoveryTokens.isEmpty()
&& priorityList != null && !priorityList.isEmpty()) {
- final int priorityIdCount = priorityList.size();
- for (int i = 0; i < priorityIdCount; i++) {
- requestPrinterUpdate(priorityList.get(i));
- }
+ validatePrinters(priorityList);
return;
}
@@ -508,20 +579,97 @@ final class UserState implements PrintSpoolerCallbacks {
.sendToTarget();
}
- public void requestPrinterUpdateLocked(PrinterId printerId) {
+ public void validatePrintersLocked(List<PrinterId> printerIds) {
if (mIsDestroyed) {
- Log.w(LOG_TAG, "Not updating pritner - session destroyed");
+ Log.w(LOG_TAG, "Not validating pritners - session destroyed");
return;
}
+
+ List<PrinterId> remainingList = new ArrayList<PrinterId>(printerIds);
+ while (!remainingList.isEmpty()) {
+ Iterator<PrinterId> iterator = remainingList.iterator();
+ // Gather the printers per service and request a validation.
+ List<PrinterId> updateList = new ArrayList<PrinterId>();
+ ComponentName serviceName = null;
+ while (iterator.hasNext()) {
+ PrinterId printerId = iterator.next();
+ if (updateList.isEmpty()) {
+ updateList.add(printerId);
+ serviceName = printerId.getServiceName();
+ iterator.remove();
+ } else if (printerId.getServiceName().equals(serviceName)) {
+ updateList.add(printerId);
+ iterator.remove();
+ }
+ }
+ // Schedule a notification of the service.
+ RemotePrintService service = mActiveServices.get(serviceName);
+ if (service != null) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = service;
+ args.arg2 = updateList;
+ mHandler.obtainMessage(SessionHandler
+ .MSG_VALIDATE_PRINTERS, args)
+ .sendToTarget();
+ }
+ }
+ }
+
+ public final void startPrinterStateTrackingLocked(PrinterId printerId) {
+ if (mIsDestroyed) {
+ Log.w(LOG_TAG, "Not starting printer state tracking - session destroyed");
+ return;
+ }
+ // If printer discovery is not started - nothing to do.
+ if (mStartedPrinterDiscoveryTokens.isEmpty()) {
+ return;
+ }
+ final boolean containedPrinterId = mStateTrackedPrinters.contains(printerId);
+ // Keep track of the number of requests to track this one.
+ mStateTrackedPrinters.add(printerId);
+ // If we were tracking this printer - nothing to do.
+ if (containedPrinterId) {
+ return;
+ }
+ // No service - nothing to do.
RemotePrintService service = mActiveServices.get(printerId.getServiceName());
- if (service != null) {
- SomeArgs args = SomeArgs.obtain();
- args.arg1 = service;
- args.arg2 = printerId;
- mHandler.obtainMessage(SessionHandler
- .MSG_REQUEST_PRINTER_UPDATE, args)
- .sendToTarget();
+ if (service == null) {
+ return;
}
+ // Ask the service to start tracking.
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = service;
+ args.arg2 = printerId;
+ mHandler.obtainMessage(SessionHandler
+ .MSG_START_PRINTER_STATE_TRACKING, args)
+ .sendToTarget();
+ }
+
+ public final void stopPrinterStateTrackingLocked(PrinterId printerId) {
+ if (mIsDestroyed) {
+ Log.w(LOG_TAG, "Not stopping printer state tracking - session destroyed");
+ return;
+ }
+ // If printer discovery is not started - nothing to do.
+ if (mStartedPrinterDiscoveryTokens.isEmpty()) {
+ return;
+ }
+ // If we did not track this printer - nothing to do.
+ if (!mStateTrackedPrinters.remove(printerId)) {
+ return;
+ }
+ // No service - nothing to do.
+ RemotePrintService service = mActiveServices.get(printerId.getServiceName());
+ if (service == null) {
+ return;
+ }
+ // Ask the service to start tracking.
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = service;
+ args.arg2 = printerId;
+ mHandler.obtainMessage(SessionHandler
+ .MSG_STOP_PRINTER_STATE_TRACKING, args)
+ .sendToTarget();
}
public void onDestroyed() {
@@ -533,6 +681,12 @@ final class UserState implements PrintSpoolerCallbacks {
Log.w(LOG_TAG, "Not destroying - session destroyed");
return;
}
+ // Make sure printer tracking is stopped.
+ final int printerCount = mStateTrackedPrinters.size();
+ for (int i = 0; i < printerCount; i++) {
+ PrinterId printerId = mStateTrackedPrinters.get(i);
+ stopPrinterStateTracking(printerId);
+ }
// Make sure discovery is stopped.
final int observerCount = mStartedPrinterDiscoveryTokens.size();
for (int i = 0; i < observerCount; i++) {
@@ -744,9 +898,19 @@ final class UserState implements PrintSpoolerCallbacks {
}
}
- private void handleRequestPrinterUpdate(RemotePrintService service,
+ private void handleValidatePrinters(RemotePrintService service,
+ List<PrinterId> printerIds) {
+ service.validatePrinters(printerIds);
+ }
+
+ private void handleStartPrinterStateTracking(RemotePrintService service,
+ PrinterId printerId) {
+ service.startPrinterStateTracking(printerId);
+ }
+
+ private void handleStopPrinterStateTracking(RemotePrintService service,
PrinterId printerId) {
- service.requestPrinterUpdate(printerId);
+ service.stopPrinterStateTracking(printerId);
}
private void handlePrintersAdded(IPrinterDiscoveryObserver observer,
@@ -804,7 +968,9 @@ final class UserState implements PrintSpoolerCallbacks {
public static final int MSG_DISPATCH_DESTROY_PRINTER_DISCOVERY_SESSION = 9;
public static final int MSG_DISPATCH_START_PRINTER_DISCOVERY = 10;
public static final int MSG_DISPATCH_STOP_PRINTER_DISCOVERY = 11;
- public static final int MSG_REQUEST_PRINTER_UPDATE = 12;
+ public static final int MSG_VALIDATE_PRINTERS = 12;
+ public static final int MSG_START_PRINTER_STATE_TRACKING = 13;
+ public static final int MSG_STOP_PRINTER_STATE_TRACKING = 14;
SessionHandler(Looper looper) {
super(looper, null, false);
@@ -878,13 +1044,29 @@ final class UserState implements PrintSpoolerCallbacks {
handleDispatchStopPrinterDiscovery(services);
} break;
- case MSG_REQUEST_PRINTER_UPDATE: {
+ case MSG_VALIDATE_PRINTERS: {
+ SomeArgs args = (SomeArgs) message.obj;
+ RemotePrintService service = (RemotePrintService) args.arg1;
+ List<PrinterId> printerIds = (List<PrinterId>) args.arg2;
+ args.recycle();
+ handleValidatePrinters(service, printerIds);
+ } break;
+
+ case MSG_START_PRINTER_STATE_TRACKING: {
SomeArgs args = (SomeArgs) message.obj;
RemotePrintService service = (RemotePrintService) args.arg1;
PrinterId printerId = (PrinterId) args.arg2;
args.recycle();
- handleRequestPrinterUpdate(service, printerId);
+ handleStartPrinterStateTracking(service, printerId);
} break;
+
+ case MSG_STOP_PRINTER_STATE_TRACKING: {
+ SomeArgs args = (SomeArgs) message.obj;
+ RemotePrintService service = (RemotePrintService) args.arg1;
+ PrinterId printerId = (PrinterId) args.arg2;
+ args.recycle();
+ handleStopPrinterStateTracking(service, printerId);
+ }
}
}
}