PrintService.java revision 798bed6cc7d273e72b0253288605db9cd2b57740
14b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/* 24b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Copyright (C) 2013 The Android Open Source Project 34b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 44b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Licensed under the Apache License, Version 2.0 (the "License"); 54b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * you may not use this file except in compliance with the License. 64b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * You may obtain a copy of the License at 74b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 84b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * http://www.apache.org/licenses/LICENSE-2.0 94b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Unless required by applicable law or agreed to in writing, software 114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * distributed under the License is distributed on an "AS IS" BASIS, 124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * See the License for the specific language governing permissions and 144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * limitations under the License. 154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovpackage android.printservice; 184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.app.Service; 204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.ComponentName; 214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.Context; 224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.content.Intent; 234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Handler; 244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.IBinder; 254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Looper; 264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.Message; 274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.RemoteException; 28798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganovimport android.print.IPrinterDiscoverySessionObserver; 294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.PrintJobInfo; 304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.PrinterId; 314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.util.Log; 324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.ArrayList; 344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.Collections; 354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.List; 364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/** 384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 39798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * This is the base class for implementing print services. A print service knows 40798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * how to discover and interact one or more printers via one or more protocols. 414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <h3>Printer discovery</h3> 434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 44798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * A print service is responsible for discovering printers, adding discovered printers, 45798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * removing added printers, and updating added printers. When the system is interested 46798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * in printers managed by your service it will call {@link 47798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * #onCreatePrinterDiscoverySession()} from which you must return a new {@link 48798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * PrinterDiscoverySession} instance. The returned session encapsulates the interaction 49798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * between the system and your service during printer discovery. For description of this 50798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * interaction refer to the documentation for {@link PrinterDiscoverySession}. 514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 53798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * For every printer discovery session all printers have to be added since system does 54798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * not retain printers across sessions. Hence, each printer known to this print service 55798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * should be added only once during a discovery session. Only an already added printer 56798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * can be removed or updated. Removed printers can be added again. 574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <h3>Print jobs</h3> 594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 60798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * When a new print job targeted to a printer managed by this print service is is queued, 61798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * i.e. ready for processing by the print service, you will receive a call to {@link 62798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * #onPrintJobQueued(PrintJob)}. The print service may handle the print job immediately 63798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * or schedule that for an appropriate time in the future. The list of all active print 64798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * jobs for this service is obtained by calling {@link #getActivePrintJobs()}. Active 65798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * print jobs are ones that are queued or started. 664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 68798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * A print service is responsible for setting a print job's state as appropriate 69798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * while processing it. Initially, a print job is queued, i.e. {@link PrintJob#isQueued() 70798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * PrintJob.isQueued()} returns true, which means that the document to be printed is 71798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * spooled by the system and the print service can begin processing it. You can obtain 72798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * the printed document by calling {@link PrintJob#getDocument() PrintJob.getDocument()} 73798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * whose data is accessed via {@link PrintDocument#getData() PrintDocument.getData()}. 74798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * After the print service starts printing the data it should set the print job's 75798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * state to started by calling {@link PrintJob#start()} after which 76798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * {@link PrintJob#isStarted() PrintJob.isStarted()} would return true. Upon successful 77798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * completion, the print job should be marked as completed by calling {@link 78798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * PrintJob#complete() PrintJob.complete()} after which {@link PrintJob#isCompleted() 79798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * PrintJob.isCompleted()} would return true. In case of a failure, the print job should 80798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * be marked as failed by calling {@link PrintJob#fail(CharSequence) PrintJob.fail( 81798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * CharSequence)} after which {@link PrintJob#isFailed() PrintJob.isFailed()} would 82798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * return true. 83a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * </p> 84a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * <p> 85798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * If a print job is queued or started and the user requests to cancel it, the print 86798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * service will receive a call to {@link #onRequestCancelPrintJob(PrintJob)} which 87798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * requests from the service to do best effort in canceling the job. In case the job 88798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * is successfully canceled, its state has to be marked as cancelled by calling {@link 89798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * PrintJob#cancel() PrintJob.cancel()} after which {@link PrintJob#isCancelled() 90798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * PrintJob.isCacnelled()} would return true. 914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <h3>Lifecycle</h3> 934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 94798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * The lifecycle of a print service is managed exclusively by the system and follows 95798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * the established service lifecycle. Additionally, starting or stopping a print service 96798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * is triggered exclusively by an explicit user action through enabling or disabling it 97798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * in the device settings. After the system binds to a print service, it calls {@link 98798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * #onConnected()}. This method can be overriden by clients to perform post binding setup. 99798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * Also after the system unbinds from a print service, it calls {@link #onDisconnected()}. 100798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * This method can be overriden by clients to perform post unbinding cleanup. Your should 101798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * not do any work after the system disconnected from your print service since the 102798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * service can be killed at any time to reclaim memory. The system will not disconnect 103798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * from a print service if there are active print jobs for the printers managed by it. 1044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 1054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <h3>Declaration</h3> 1064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 107798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * A print service is declared as any other service in an AndroidManifest.xml but it must 108798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * also specify that it handles the {@link android.content.Intent} with action {@link 109798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * #SERVICE_INTERFACE android.printservice.PrintService}. Failure to declare this intent 110798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * will cause the system to ignore the print service. Additionally, a print service must 111798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * request the {@link android.Manifest.permission#BIND_PRINT_SERVICE 112798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * android.permission.BIND_PRINT_SERVICE} permission to ensure that only the system can 113798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * bind to it. Failure to declare this intent will cause the system to ignore the print 114798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * service. Following is an example declaration: 1154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 1164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <pre> 1174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <service android:name=".MyPrintService" 1184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * android:permission="android.permission.BIND_PRINT_SERVICE"> 1194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <intent-filter> 1204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <action android:name="android.printservice.PrintService" /> 1214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </intent-filter> 1224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * . . . 1234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </service> 1244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </pre> 1254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <h3>Configuration</h3> 1264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 127798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * A print service can be configured by specifying an optional settings activity which 128798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * exposes service specific settings, an optional add printers activity which is used for 129798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * manual addition of printers, vendor name ,etc. It is a responsibility of the system 130798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * to launch the settings and add printers activities when appropriate. 1314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 1324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 133798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * A print service is configured by providing a {@link #SERVICE_META_DATA meta-data} 134798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * entry in the manifest when declaring the service. A service declaration with a meta-data 135798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * tag is presented below: 1364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <pre> <service android:name=".MyPrintService" 1374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * android:permission="android.permission.BIND_PRINT_SERVICE"> 1384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <intent-filter> 1394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <action android:name="android.printservice.PrintService" /> 1404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </intent-filter> 1414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <meta-data android:name="android.printservice" android:resource="@xml/printservice" /> 1424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </service></pre> 1434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 1444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 145798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * For more details for how to configure your print service via the meta-data refer to 146798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * {@link #SERVICE_META_DATA} and <code><{@link android.R.styleable#PrintService 147798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * print-service}></code>. 1484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 1494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 1504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovpublic abstract class PrintService extends Service { 1514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 152a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private static final String LOG_TAG = "PrintService"; 1534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 1554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * The {@link Intent} action that must be declared as handled by a service 156798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * in its manifest for the system to recognize it as a print service. 1574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 1584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public static final String SERVICE_INTERFACE = "android.printservice.PrintService"; 1594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 161798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * Name under which a {@link PrintService} component publishes additional information 162798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * about itself. This meta-data must reference a XML resource containing a <code> 163798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * <{@link android.R.styleable#PrintService print-service}></code> tag. This is 164798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * a sample XML file configuring a print service: 1654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <pre> <print-service 166a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * android:vendor="SomeVendor" 1674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * android:settingsActivity="foo.bar.MySettingsActivity" 1684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * andorid:addPrintersActivity="foo.bar.MyAddPrintersActivity." 1694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * . . . 1704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * /></pre> 171798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * <p> 172798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * For detailed configuration options that can be specified via the meta-data 173798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * refer to {@link android.R.styleable#PrintService android.R.styleable.PrintService}. 174798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * </p> 1754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 1764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public static final String SERVICE_META_DATA = "android.printservice"; 1774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final Object mLock = new Object(); 1794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private Handler mHandler; 1814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private IPrintServiceClient mClient; 1834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 184798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov private int mLastSessionId = -1; 1854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1864b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 187798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov protected final void attachBaseContext(Context base) { 1884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov super.attachBaseContext(base); 189798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov mHandler = new ServiceHandler(base.getMainLooper()); 1904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 1934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * The system has connected to this service. 1944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 1954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov protected void onConnected() { 1964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /* do nothing */ 1974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 2004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * The system has disconnected from this service. 2014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 2024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov protected void onDisconnected() { 2034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /* do nothing */ 2044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 207798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * Callback asking you to create a new {@link PrinterDiscoverySession}. 2084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 209798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @see PrinterDiscoverySession 2104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 211798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov protected abstract PrinterDiscoverySession onCreatePrinterDiscoverySession(); 2124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 214798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * Called when cancellation of a print job is requested. The service 215a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * should do best effort to fulfill the request. After the cancellation 216798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * is performed, the print job should be marked as cancelled state by 217a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * calling {@link PrintJob#cancel()}. 2184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 219798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @param printJob The print job to cancel. 220798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * 221798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @see PrintJob#cancel() PrintJob.cancel() 222798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @see PrintJob#isCancelled() PrintJob.isCancelled() 2234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 224798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov protected abstract void onRequestCancelPrintJob(PrintJob printJob); 2254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 2274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Called when there is a queued print job for one of the printers 228798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * managed by this print service. 2294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 2304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @param printJob The new queued print job. 2314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 232798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @see PrintJob#isQueued() PrintJob.isQueued() 233798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @see #getActivePrintJobs() 2344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 2354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov protected abstract void onPrintJobQueued(PrintJob printJob); 2364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 238798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * Gets the active print jobs for the printers managed by this service. 239798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * Active print jobs are ones that are not in a final state, i.e. whose 240798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * state is queued or started. 2414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 242798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @return The active print jobs. 243798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * 244798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @see PrintJob#isQueued() PrintJob.isQueued() 245798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @see PrintJob#isStarted() PrintJob.isStarted() 2464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 247798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov public final List<PrintJob> getActivePrintJobs() { 248a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final IPrintServiceClient client; 2494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov synchronized (mLock) { 250a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov client = mClient; 251a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 252a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (client == null) { 253a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return Collections.emptyList(); 254a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 255a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov try { 256a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov List<PrintJob> printJobs = null; 257a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov List<PrintJobInfo> printJobInfos = client.getPrintJobInfos(); 258a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (printJobInfos != null) { 259a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final int printJobInfoCount = printJobInfos.size(); 260a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov printJobs = new ArrayList<PrintJob>(printJobInfoCount); 261a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov for (int i = 0; i < printJobInfoCount; i++) { 262a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov printJobs.add(new PrintJob(printJobInfos.get(i), client)); 2634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 265a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (printJobs != null) { 266a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return printJobs; 267a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 268a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } catch (RemoteException re) { 269a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Log.e(LOG_TAG, "Error calling getPrintJobs()", re); 2704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 271a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return Collections.emptyList(); 2724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 275798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * Generates a global printer id given the printer's locally unique one. 2764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 277798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @param localId A locally unique id in the context of your print service. 2784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @return Global printer id. 2794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 280798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov public final PrinterId generatePrinterId(String localId) { 2814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return new PrinterId(new ComponentName(getPackageName(), 282798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov getClass().getName()), localId); 2834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2844b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 2864b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public final IBinder onBind(Intent intent) { 2874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return new IPrintService.Stub() { 2884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 2894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void setClient(IPrintServiceClient client) { 290798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov mHandler.obtainMessage(ServiceHandler.MSG_SET_CLEINT, client) 291798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov .sendToTarget(); 2924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 295798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) { 296798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov mHandler.obtainMessage(ServiceHandler.MSG_ON_CREATE_PRINTER_DISCOVERY_SESSION, 297a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov observer).sendToTarget(); 2984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 3004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 301798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov public void requestCancelPrintJob(PrintJobInfo printJobInfo) { 302798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov mHandler.obtainMessage(ServiceHandler.MSG_ON_REQUEST_CANCEL_PRINTJOB, 303a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov printJobInfo).sendToTarget(); 3044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 3064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 307a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onPrintJobQueued(PrintJobInfo printJobInfo) { 308798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov mHandler.obtainMessage(ServiceHandler.MSG_ON_PRINTJOB_QUEUED, 309a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov printJobInfo).sendToTarget(); 3104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov }; 3124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 314798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov private final class ServiceHandler extends Handler { 315798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov public static final int MSG_ON_CREATE_PRINTER_DISCOVERY_SESSION = 1; 316798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov public static final int MSG_ON_PRINTJOB_QUEUED = 2; 31755b409a97cf6376399a0940313ea852368727d6fSvetoslav Ganov public static final int MSG_ON_REQUEST_CANCEL_PRINTJOB = 3; 318798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov public static final int MSG_SET_CLEINT = 4; 3194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 320798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov public ServiceHandler(Looper looper) { 3214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov super(looper, null, true); 3224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 3244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 3254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void handleMessage(Message message) { 3264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov final int action = message.what; 3274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov switch (action) { 328798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov case MSG_ON_CREATE_PRINTER_DISCOVERY_SESSION: { 329798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov IPrinterDiscoverySessionObserver observer = 330798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov (IPrinterDiscoverySessionObserver) message.obj; 331798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov PrinterDiscoverySession session = onCreatePrinterDiscoverySession(); 332798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov if (session == null) { 333798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov throw new NullPointerException("session cannot be null"); 3344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov synchronized (mLock) { 336798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov if (session.getId() == mLastSessionId) { 337798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov throw new IllegalStateException("cannot reuse sessions"); 338798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov } 339798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov mLastSessionId = session.getId(); 3404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 341798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov session.setObserver(observer); 3424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } break; 3434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 34455b409a97cf6376399a0940313ea852368727d6fSvetoslav Ganov case MSG_ON_REQUEST_CANCEL_PRINTJOB: { 345a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov PrintJobInfo printJobInfo = (PrintJobInfo) message.obj; 346a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov onRequestCancelPrintJob(new PrintJob(printJobInfo, mClient)); 3474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } break; 3484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 34955b409a97cf6376399a0940313ea852368727d6fSvetoslav Ganov case MSG_ON_PRINTJOB_QUEUED: { 350a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov PrintJobInfo printJobInfo = (PrintJobInfo) message.obj; 351a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov onPrintJobQueued(new PrintJob(printJobInfo, mClient)); 3524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } break; 3534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 35455b409a97cf6376399a0940313ea852368727d6fSvetoslav Ganov case MSG_SET_CLEINT: { 3554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov IPrintServiceClient client = (IPrintServiceClient) message.obj; 3564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov synchronized (mLock) { 3574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mClient = client; 3584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (client != null) { 3604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov onConnected(); 3614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } else { 3624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov onDisconnected(); 3634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } break; 3654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 3664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov default: { 3674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov throw new IllegalArgumentException("Unknown message: " + action); 3684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov} 373