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; 284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.PrintJobInfo; 294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.print.PrinterId; 304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.util.Log; 314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.ArrayList; 334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.Collections; 344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.List; 354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/** 374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 38798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * This is the base class for implementing print services. A print service knows 39798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * how to discover and interact one or more printers via one or more protocols. 404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <h3>Printer discovery</h3> 424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 43798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * A print service is responsible for discovering printers, adding discovered printers, 44798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * removing added printers, and updating added printers. When the system is interested 45798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * in printers managed by your service it will call {@link 46798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * #onCreatePrinterDiscoverySession()} from which you must return a new {@link 47798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * PrinterDiscoverySession} instance. The returned session encapsulates the interaction 48798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * between the system and your service during printer discovery. For description of this 49798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * interaction refer to the documentation for {@link PrinterDiscoverySession}. 504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 52798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * For every printer discovery session all printers have to be added since system does 53798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * not retain printers across sessions. Hence, each printer known to this print service 54798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * should be added only once during a discovery session. Only an already added printer 55798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * can be removed or updated. Removed printers can be added again. 564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <h3>Print jobs</h3> 584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 59798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * When a new print job targeted to a printer managed by this print service is is queued, 60798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * i.e. ready for processing by the print service, you will receive a call to {@link 61798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * #onPrintJobQueued(PrintJob)}. The print service may handle the print job immediately 62798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * or schedule that for an appropriate time in the future. The list of all active print 63798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * jobs for this service is obtained by calling {@link #getActivePrintJobs()}. Active 64798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * print jobs are ones that are queued or started. 654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 67798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * A print service is responsible for setting a print job's state as appropriate 68798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * while processing it. Initially, a print job is queued, i.e. {@link PrintJob#isQueued() 69798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * PrintJob.isQueued()} returns true, which means that the document to be printed is 70798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * spooled by the system and the print service can begin processing it. You can obtain 71798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * the printed document by calling {@link PrintJob#getDocument() PrintJob.getDocument()} 72798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * whose data is accessed via {@link PrintDocument#getData() PrintDocument.getData()}. 73798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * After the print service starts printing the data it should set the print job's 74798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * state to started by calling {@link PrintJob#start()} after which 75798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * {@link PrintJob#isStarted() PrintJob.isStarted()} would return true. Upon successful 76798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * completion, the print job should be marked as completed by calling {@link 77798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * PrintJob#complete() PrintJob.complete()} after which {@link PrintJob#isCompleted() 78798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * PrintJob.isCompleted()} would return true. In case of a failure, the print job should 793bf7976e78d69310b67f4f19f49b2eb839252b67Svetoslav Ganov * be marked as failed by calling {@link PrintJob#fail(String) PrintJob.fail( 803bf7976e78d69310b67f4f19f49b2eb839252b67Svetoslav Ganov * String)} after which {@link PrintJob#isFailed() PrintJob.isFailed()} would 81798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * return true. 82a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * </p> 83a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * <p> 84798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * If a print job is queued or started and the user requests to cancel it, the print 85798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * service will receive a call to {@link #onRequestCancelPrintJob(PrintJob)} which 86798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * requests from the service to do best effort in canceling the job. In case the job 87798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * is successfully canceled, its state has to be marked as cancelled by calling {@link 88798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * PrintJob#cancel() PrintJob.cancel()} after which {@link PrintJob#isCancelled() 89798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * PrintJob.isCacnelled()} would return true. 904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <h3>Lifecycle</h3> 924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 93798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * The lifecycle of a print service is managed exclusively by the system and follows 94798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * the established service lifecycle. Additionally, starting or stopping a print service 95798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * is triggered exclusively by an explicit user action through enabling or disabling it 96798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * in the device settings. After the system binds to a print service, it calls {@link 97798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * #onConnected()}. This method can be overriden by clients to perform post binding setup. 98798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * Also after the system unbinds from a print service, it calls {@link #onDisconnected()}. 99798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * This method can be overriden by clients to perform post unbinding cleanup. Your should 100798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * not do any work after the system disconnected from your print service since the 101798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * service can be killed at any time to reclaim memory. The system will not disconnect 102798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * from a print service if there are active print jobs for the printers managed by it. 1034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 1044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <h3>Declaration</h3> 1054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 106798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * A print service is declared as any other service in an AndroidManifest.xml but it must 107798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * also specify that it handles the {@link android.content.Intent} with action {@link 108798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * #SERVICE_INTERFACE android.printservice.PrintService}. Failure to declare this intent 109798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * will cause the system to ignore the print service. Additionally, a print service must 110798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * request the {@link android.Manifest.permission#BIND_PRINT_SERVICE 111798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * android.permission.BIND_PRINT_SERVICE} permission to ensure that only the system can 112798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * bind to it. Failure to declare this intent will cause the system to ignore the print 113798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * service. Following is an example declaration: 1144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 1154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <pre> 1164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <service android:name=".MyPrintService" 1174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * android:permission="android.permission.BIND_PRINT_SERVICE"> 1184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <intent-filter> 1194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <action android:name="android.printservice.PrintService" /> 1204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </intent-filter> 1214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * . . . 1224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </service> 1234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </pre> 1244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <h3>Configuration</h3> 1254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 126798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * A print service can be configured by specifying an optional settings activity which 127798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * exposes service specific settings, an optional add printers activity which is used for 128798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * manual addition of printers, vendor name ,etc. It is a responsibility of the system 129798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * to launch the settings and add printers activities when appropriate. 1304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 1314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 132798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * A print service is configured by providing a {@link #SERVICE_META_DATA meta-data} 133798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * entry in the manifest when declaring the service. A service declaration with a meta-data 134798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * tag is presented below: 1354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <pre> <service android:name=".MyPrintService" 1364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * android:permission="android.permission.BIND_PRINT_SERVICE"> 1374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <intent-filter> 1384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <action android:name="android.printservice.PrintService" /> 1394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </intent-filter> 1404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <meta-data android:name="android.printservice" android:resource="@xml/printservice" /> 1414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </service></pre> 1424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 1434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p> 144798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * For more details for how to configure your print service via the meta-data refer to 145798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * {@link #SERVICE_META_DATA} and <code><{@link android.R.styleable#PrintService 146798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * print-service}></code>. 1474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p> 148269403b032f965ff3847eb982c2f697229dc5a92Svetoslav * <p> 149269403b032f965ff3847eb982c2f697229dc5a92Svetoslav * <strong>Note: </strong> All callbacks in this class are executed on the main 150269403b032f965ff3847eb982c2f697229dc5a92Svetoslav * application thread. You should also invoke any method of this class on the main 151269403b032f965ff3847eb982c2f697229dc5a92Svetoslav * application thread. 152269403b032f965ff3847eb982c2f697229dc5a92Svetoslav * </p> 1534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 1544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovpublic abstract class PrintService extends Service { 1554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 156a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private static final String LOG_TAG = "PrintService"; 1574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 158b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov private static final boolean DEBUG = false; 159b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov 1604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 1614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * The {@link Intent} action that must be declared as handled by a service 162798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * in its manifest for the system to recognize it as a print service. 1634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 1644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public static final String SERVICE_INTERFACE = "android.printservice.PrintService"; 1654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 167798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * Name under which a {@link PrintService} component publishes additional information 168798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * about itself. This meta-data must reference a XML resource containing a <code> 169798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * <{@link android.R.styleable#PrintService print-service}></code> tag. This is 170798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * a sample XML file configuring a print service: 1714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <pre> <print-service 172a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * android:vendor="SomeVendor" 1734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * android:settingsActivity="foo.bar.MySettingsActivity" 1744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * andorid:addPrintersActivity="foo.bar.MyAddPrintersActivity." 1754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * . . . 1764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * /></pre> 177798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * <p> 178798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * For detailed configuration options that can be specified via the meta-data 179798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * refer to {@link android.R.styleable#PrintService android.R.styleable.PrintService}. 180798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * </p> 181860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov * <p> 182860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov * If you declare a settings or add a printers activity, they have to be exported, 183860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov * by setting the {@link android.R.attr#exported} activity attribute to <code>true 184860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov * </code>. Also in case you want only the system to be able to start any of these 185860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov * activities you can specify that they request the android.permission 186860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov * .START_PRINT_SERVICE_CONFIG_ACTIVITY permission by setting the 187860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov * {@link android.R.attr#permission} activity attribute. 188860f8a6b663ca96d30d17da09eca8caf065aae62Svetoslav Ganov * </p> 1894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 1904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public static final String SERVICE_META_DATA = "android.printservice"; 1914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1921c43fceaaa5f9aa6e29e2670f44f312632241007Svetoslav /** 1931c43fceaaa5f9aa6e29e2670f44f312632241007Svetoslav * If you declared an optional activity with advanced print options via the 1940d9ada9fdd1a609ded3fed4328021a5fe26d898dNarayan Kamath * {@link android.R.attr#advancedPrintOptionsActivity advancedPrintOptionsActivity} 1951c43fceaaa5f9aa6e29e2670f44f312632241007Svetoslav * attribute, this extra is used to pass in the currently constructed {@link 1961c43fceaaa5f9aa6e29e2670f44f312632241007Svetoslav * PrintJobInfo} to your activity allowing you to modify it. After you are 1971c43fceaaa5f9aa6e29e2670f44f312632241007Svetoslav * done, you must return the modified {@link PrintJobInfo} via the same extra. 1981c43fceaaa5f9aa6e29e2670f44f312632241007Svetoslav * <p> 1991c43fceaaa5f9aa6e29e2670f44f312632241007Svetoslav * You cannot modify the passed in {@link PrintJobInfo} directly, rather you 2001c43fceaaa5f9aa6e29e2670f44f312632241007Svetoslav * should build another one using the {@link PrintJobInfo.Builder} class. You 2011c43fceaaa5f9aa6e29e2670f44f312632241007Svetoslav * can specify any standard properties and add advanced, printer specific, 2021c43fceaaa5f9aa6e29e2670f44f312632241007Svetoslav * ones via {@link PrintJobInfo.Builder#putAdvancedOption(String, String) 203a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * PrintJobInfo.Builder.putAdvancedOption(String, String)} and {@link 2041c43fceaaa5f9aa6e29e2670f44f312632241007Svetoslav * PrintJobInfo.Builder#putAdvancedOption(String, int) 205a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * PrintJobInfo.Builder.putAdvancedOption(String, int)}. The advanced options 2061c43fceaaa5f9aa6e29e2670f44f312632241007Svetoslav * are not interpreted by the system, they will not be visible to applications, 2071c43fceaaa5f9aa6e29e2670f44f312632241007Svetoslav * and can only be accessed by your print service via {@link 2081c43fceaaa5f9aa6e29e2670f44f312632241007Svetoslav * PrintJob#getAdvancedStringOption(String) PrintJob.getAdvancedStringOption(String)} 2091c43fceaaa5f9aa6e29e2670f44f312632241007Svetoslav * and {@link PrintJob#getAdvancedIntOption(String) PrintJob.getAdvancedIntOption(String)}. 2101c43fceaaa5f9aa6e29e2670f44f312632241007Svetoslav * </p> 211b4fda134761c9521a7e127db3806a07a18763b77Svetoslav * <p> 212b4fda134761c9521a7e127db3806a07a18763b77Svetoslav * If the advanced print options activity offers changes to the standard print 213b4fda134761c9521a7e127db3806a07a18763b77Svetoslav * options, you can get the current {@link android.print.PrinterInfo} using the 214a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * {@link #EXTRA_PRINTER_INFO} extra which will allow you to present the user 215a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * with UI options supported by the current printer. For example, if the current 216a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * printer does not support a given media size, you should not offer it in the 217a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * advanced print options UI. 218b4fda134761c9521a7e127db3806a07a18763b77Svetoslav * </p> 219a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * 220a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * @see #EXTRA_PRINTER_INFO 2211c43fceaaa5f9aa6e29e2670f44f312632241007Svetoslav */ 2221c43fceaaa5f9aa6e29e2670f44f312632241007Svetoslav public static final String EXTRA_PRINT_JOB_INFO = "android.intent.extra.print.PRINT_JOB_INFO"; 2231c43fceaaa5f9aa6e29e2670f44f312632241007Svetoslav 224a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav /** 225a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * If you declared an optional activity with advanced print options via the 2260d9ada9fdd1a609ded3fed4328021a5fe26d898dNarayan Kamath * {@link android.R.attr#advancedPrintOptionsActivity advancedPrintOptionsActivity} 227a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * attribute, this extra is used to pass in the currently selected printer's 228a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * {@link android.print.PrinterInfo} to your activity allowing you to inspect it. 229a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * 230a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav * @see #EXTRA_PRINT_JOB_INFO 231a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav */ 2328fbd0dc30328338cb7a6675ce7e0fe48a7815e1bSvet Ganov public static final String EXTRA_PRINTER_INFO = "android.intent.extra.print.EXTRA_PRINTER_INFO"; 233a798c0a984f29f7180883a61839f68d2cbf0c6ceSvetoslav 2345772b5c671a13d9c4bbc1e3803667166f811cb33Svet Ganov /** 2355772b5c671a13d9c4bbc1e3803667166f811cb33Svet Ganov * If you declared an optional activity with advanced print options via the 2365772b5c671a13d9c4bbc1e3803667166f811cb33Svet Ganov * {@link android.R.attr#advancedPrintOptionsActivity advancedPrintOptionsActivity} 2375772b5c671a13d9c4bbc1e3803667166f811cb33Svet Ganov * attribute, this extra is used to pass in the meta-data for the currently printed 2385772b5c671a13d9c4bbc1e3803667166f811cb33Svet Ganov * document as a {@link android.print.PrintDocumentInfo} to your activity allowing 2395772b5c671a13d9c4bbc1e3803667166f811cb33Svet Ganov * you to inspect it. 2405772b5c671a13d9c4bbc1e3803667166f811cb33Svet Ganov * 2415772b5c671a13d9c4bbc1e3803667166f811cb33Svet Ganov * @see #EXTRA_PRINT_JOB_INFO 2425772b5c671a13d9c4bbc1e3803667166f811cb33Svet Ganov * @see #EXTRA_PRINTER_INFO 2435772b5c671a13d9c4bbc1e3803667166f811cb33Svet Ganov */ 2445772b5c671a13d9c4bbc1e3803667166f811cb33Svet Ganov public static final String EXTRA_PRINT_DOCUMENT_INFO = 2455772b5c671a13d9c4bbc1e3803667166f811cb33Svet Ganov "android.printservice.extra.PRINT_DOCUMENT_INFO"; 2465772b5c671a13d9c4bbc1e3803667166f811cb33Svet Ganov 2474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private Handler mHandler; 2484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private IPrintServiceClient mClient; 2504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 251798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov private int mLastSessionId = -1; 2524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 253269403b032f965ff3847eb982c2f697229dc5a92Svetoslav private PrinterDiscoverySession mDiscoverySession; 254269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 2554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 256798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov protected final void attachBaseContext(Context base) { 2574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov super.attachBaseContext(base); 258798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov mHandler = new ServiceHandler(base.getMainLooper()); 2594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 2624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * The system has connected to this service. 2634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 2644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov protected void onConnected() { 2654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /* do nothing */ 2664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 2694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * The system has disconnected from this service. 2704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 2714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov protected void onDisconnected() { 2724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /* do nothing */ 2734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 2744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 276798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * Callback asking you to create a new {@link PrinterDiscoverySession}. 2774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 278798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @see PrinterDiscoverySession 2794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 280798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov protected abstract PrinterDiscoverySession onCreatePrinterDiscoverySession(); 2814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 283798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * Called when cancellation of a print job is requested. The service 284a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * should do best effort to fulfill the request. After the cancellation 285798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * is performed, the print job should be marked as cancelled state by 286a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov * calling {@link PrintJob#cancel()}. 2874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 288798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @param printJob The print job to cancel. 289798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * 290798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @see PrintJob#cancel() PrintJob.cancel() 291798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @see PrintJob#isCancelled() PrintJob.isCancelled() 2924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 293798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov protected abstract void onRequestCancelPrintJob(PrintJob printJob); 2944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 2964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Called when there is a queued print job for one of the printers 297798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * managed by this print service. 2984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 2994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @param printJob The new queued print job. 3004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 301798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @see PrintJob#isQueued() PrintJob.isQueued() 302798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @see #getActivePrintJobs() 3034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 3044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov protected abstract void onPrintJobQueued(PrintJob printJob); 3054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 3064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 307798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * Gets the active print jobs for the printers managed by this service. 308798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * Active print jobs are ones that are not in a final state, i.e. whose 309798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * state is queued or started. 3104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 311798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @return The active print jobs. 312798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * 313798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @see PrintJob#isQueued() PrintJob.isQueued() 314798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @see PrintJob#isStarted() PrintJob.isStarted() 3154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 316798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov public final List<PrintJob> getActivePrintJobs() { 317269403b032f965ff3847eb982c2f697229dc5a92Svetoslav throwIfNotCalledOnMainThread(); 318269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (mClient == null) { 319a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return Collections.emptyList(); 320a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 321a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov try { 322a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov List<PrintJob> printJobs = null; 323269403b032f965ff3847eb982c2f697229dc5a92Svetoslav List<PrintJobInfo> printJobInfos = mClient.getPrintJobInfos(); 324a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (printJobInfos != null) { 325a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov final int printJobInfoCount = printJobInfos.size(); 326a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov printJobs = new ArrayList<PrintJob>(printJobInfoCount); 327a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov for (int i = 0; i < printJobInfoCount; i++) { 328269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printJobs.add(new PrintJob(printJobInfos.get(i), mClient)); 3294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 331a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov if (printJobs != null) { 332a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return printJobs; 333a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 334a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } catch (RemoteException re) { 335a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov Log.e(LOG_TAG, "Error calling getPrintJobs()", re); 3364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 337a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov return Collections.emptyList(); 3384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 3404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov /** 341798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * Generates a global printer id given the printer's locally unique one. 3424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 343798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @param localId A locally unique id in the context of your print service. 3444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * @return Global printer id. 3454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 346798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov public final PrinterId generatePrinterId(String localId) { 347269403b032f965ff3847eb982c2f697229dc5a92Svetoslav throwIfNotCalledOnMainThread(); 3484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return new PrinterId(new ComponentName(getPackageName(), 349798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov getClass().getName()), localId); 3504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 352269403b032f965ff3847eb982c2f697229dc5a92Svetoslav static void throwIfNotCalledOnMainThread() { 353269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (!Looper.getMainLooper().isCurrentThread()) { 354269403b032f965ff3847eb982c2f697229dc5a92Svetoslav throw new IllegalAccessError("must be called from the main thread"); 355269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 356269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 357269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 3584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 3594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public final IBinder onBind(Intent intent) { 3604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return new IPrintService.Stub() { 3614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 362269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public void createPrinterDiscoverySession() { 363269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mHandler.sendEmptyMessage(ServiceHandler.MSG_CREATE_PRINTER_DISCOVERY_SESSION); 364269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 365269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 366269403b032f965ff3847eb982c2f697229dc5a92Svetoslav @Override 367269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public void destroyPrinterDiscoverySession() { 368269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mHandler.sendEmptyMessage(ServiceHandler.MSG_DESTROY_PRINTER_DISCOVERY_SESSION); 369269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 370269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 371269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public void startPrinterDiscovery(List<PrinterId> priorityList) { 372269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mHandler.obtainMessage(ServiceHandler.MSG_START_PRINTER_DISCOVERY, 373269403b032f965ff3847eb982c2f697229dc5a92Svetoslav priorityList).sendToTarget(); 3744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 3754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 3764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 377269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public void stopPrinterDiscovery() { 378269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mHandler.sendEmptyMessage(ServiceHandler.MSG_STOP_PRINTER_DISCOVERY); 379269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 380269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 381269403b032f965ff3847eb982c2f697229dc5a92Svetoslav @Override 382d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov public void validatePrinters(List<PrinterId> printerIds) { 383d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov mHandler.obtainMessage(ServiceHandler.MSG_VALIDATE_PRINTERS, 384d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov printerIds).sendToTarget(); 385d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov } 386d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov 387d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov @Override 388d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov public void startPrinterStateTracking(PrinterId printerId) { 389d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov mHandler.obtainMessage(ServiceHandler.MSG_START_PRINTER_STATE_TRACKING, 390d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov printerId).sendToTarget(); 391d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov } 392d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov 393d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov @Override 394d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov public void stopPrinterStateTracking(PrinterId printerId) { 395d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov mHandler.obtainMessage(ServiceHandler.MSG_STOP_PRINTER_STATE_TRACKING, 396269403b032f965ff3847eb982c2f697229dc5a92Svetoslav printerId).sendToTarget(); 397269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 398269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 399269403b032f965ff3847eb982c2f697229dc5a92Svetoslav @Override 400269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public void setClient(IPrintServiceClient client) { 401eae626fd8c9ecb91c43ccb1dda050de52f9795c0jangwon.lee mHandler.obtainMessage(ServiceHandler.MSG_SET_CLIENT, client) 402269403b032f965ff3847eb982c2f697229dc5a92Svetoslav .sendToTarget(); 4034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 4054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 406798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov public void requestCancelPrintJob(PrintJobInfo printJobInfo) { 407798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov mHandler.obtainMessage(ServiceHandler.MSG_ON_REQUEST_CANCEL_PRINTJOB, 408a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov printJobInfo).sendToTarget(); 4094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 4114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 412a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onPrintJobQueued(PrintJobInfo printJobInfo) { 413798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov mHandler.obtainMessage(ServiceHandler.MSG_ON_PRINTJOB_QUEUED, 414a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov printJobInfo).sendToTarget(); 4154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov }; 4174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 419798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov private final class ServiceHandler extends Handler { 420269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public static final int MSG_CREATE_PRINTER_DISCOVERY_SESSION = 1; 421269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public static final int MSG_DESTROY_PRINTER_DISCOVERY_SESSION = 2; 422269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public static final int MSG_START_PRINTER_DISCOVERY = 3; 423269403b032f965ff3847eb982c2f697229dc5a92Svetoslav public static final int MSG_STOP_PRINTER_DISCOVERY = 4; 424d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov public static final int MSG_VALIDATE_PRINTERS = 5; 425d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov public static final int MSG_START_PRINTER_STATE_TRACKING = 6; 426d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov public static final int MSG_STOP_PRINTER_STATE_TRACKING = 7; 427d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov public static final int MSG_ON_PRINTJOB_QUEUED = 8; 428d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov public static final int MSG_ON_REQUEST_CANCEL_PRINTJOB = 9; 429eae626fd8c9ecb91c43ccb1dda050de52f9795c0jangwon.lee public static final int MSG_SET_CLIENT = 10; 4304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 431798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov public ServiceHandler(Looper looper) { 4324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov super(looper, null, true); 4334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 4344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 4354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 436269403b032f965ff3847eb982c2f697229dc5a92Svetoslav @SuppressWarnings("unchecked") 4374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void handleMessage(Message message) { 4384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov final int action = message.what; 4394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov switch (action) { 440269403b032f965ff3847eb982c2f697229dc5a92Svetoslav case MSG_CREATE_PRINTER_DISCOVERY_SESSION: { 441b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav if (DEBUG) { 442b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav Log.i(LOG_TAG, "MSG_CREATE_PRINTER_DISCOVERY_SESSION " 443b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav + getPackageName()); 444b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav } 445798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov PrinterDiscoverySession session = onCreatePrinterDiscoverySession(); 446798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov if (session == null) { 447798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov throw new NullPointerException("session cannot be null"); 4484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 449269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (session.getId() == mLastSessionId) { 450269403b032f965ff3847eb982c2f697229dc5a92Svetoslav throw new IllegalStateException("cannot reuse session instances"); 451269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 452269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mDiscoverySession = session; 453269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mLastSessionId = session.getId(); 454269403b032f965ff3847eb982c2f697229dc5a92Svetoslav session.setObserver(mClient); 455269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } break; 456269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 457269403b032f965ff3847eb982c2f697229dc5a92Svetoslav case MSG_DESTROY_PRINTER_DISCOVERY_SESSION: { 458b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav if (DEBUG) { 459b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav Log.i(LOG_TAG, "MSG_DESTROY_PRINTER_DISCOVERY_SESSION " 460b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav + getPackageName()); 461b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav } 462269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (mDiscoverySession != null) { 463269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mDiscoverySession.destroy(); 464269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mDiscoverySession = null; 465269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 466269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } break; 467269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 468269403b032f965ff3847eb982c2f697229dc5a92Svetoslav case MSG_START_PRINTER_DISCOVERY: { 469b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav if (DEBUG) { 470b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav Log.i(LOG_TAG, "MSG_START_PRINTER_DISCOVERY " 471b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav + getPackageName()); 472b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav } 473269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (mDiscoverySession != null) { 474269403b032f965ff3847eb982c2f697229dc5a92Svetoslav List<PrinterId> priorityList = (ArrayList<PrinterId>) message.obj; 475269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mDiscoverySession.startPrinterDiscovery(priorityList); 476269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 477269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } break; 478269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 479269403b032f965ff3847eb982c2f697229dc5a92Svetoslav case MSG_STOP_PRINTER_DISCOVERY: { 480b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav if (DEBUG) { 481b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav Log.i(LOG_TAG, "MSG_STOP_PRINTER_DISCOVERY " 482b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav + getPackageName()); 483b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav } 484269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (mDiscoverySession != null) { 485269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mDiscoverySession.stopPrinterDiscovery(); 486269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 487269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } break; 488269403b032f965ff3847eb982c2f697229dc5a92Svetoslav 489d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov case MSG_VALIDATE_PRINTERS: { 490b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav if (DEBUG) { 491b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav Log.i(LOG_TAG, "MSG_VALIDATE_PRINTERS " 492b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav + getPackageName()); 493b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav } 494d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov if (mDiscoverySession != null) { 495d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov List<PrinterId> printerIds = (List<PrinterId>) message.obj; 496d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov mDiscoverySession.validatePrinters(printerIds); 497d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov } 498d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov } break; 499d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov 500d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov case MSG_START_PRINTER_STATE_TRACKING: { 501b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav if (DEBUG) { 502b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav Log.i(LOG_TAG, "MSG_START_PRINTER_STATE_TRACKING " 503b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav + getPackageName()); 504b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav } 505d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov if (mDiscoverySession != null) { 506d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov PrinterId printerId = (PrinterId) message.obj; 507d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov mDiscoverySession.startPrinterStateTracking(printerId); 508d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov } 509d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov } break; 510d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov 511d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov case MSG_STOP_PRINTER_STATE_TRACKING: { 512b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav if (DEBUG) { 513b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav Log.i(LOG_TAG, "MSG_STOP_PRINTER_STATE_TRACKING " 514b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav + getPackageName()); 515b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav } 516269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (mDiscoverySession != null) { 517269403b032f965ff3847eb982c2f697229dc5a92Svetoslav PrinterId printerId = (PrinterId) message.obj; 518d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov mDiscoverySession.stopPrinterStateTracking(printerId); 5194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 5204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } break; 5214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 52255b409a97cf6376399a0940313ea852368727d6fSvetoslav Ganov case MSG_ON_REQUEST_CANCEL_PRINTJOB: { 523b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav if (DEBUG) { 524b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav Log.i(LOG_TAG, "MSG_ON_REQUEST_CANCEL_PRINTJOB " 525b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav + getPackageName()); 526b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav } 527a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov PrintJobInfo printJobInfo = (PrintJobInfo) message.obj; 528a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov onRequestCancelPrintJob(new PrintJob(printJobInfo, mClient)); 5294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } break; 5304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 53155b409a97cf6376399a0940313ea852368727d6fSvetoslav Ganov case MSG_ON_PRINTJOB_QUEUED: { 532b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav if (DEBUG) { 533b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav Log.i(LOG_TAG, "MSG_ON_PRINTJOB_QUEUED " 534b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav + getPackageName()); 535b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav } 536a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov PrintJobInfo printJobInfo = (PrintJobInfo) message.obj; 537b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov if (DEBUG) { 538b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov Log.i(LOG_TAG, "Queued: " + printJobInfo); 539b669917825a49421ee79be4819ead765f5de8aaeSvetoslav Ganov } 540a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov onPrintJobQueued(new PrintJob(printJobInfo, mClient)); 5414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } break; 5424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 543eae626fd8c9ecb91c43ccb1dda050de52f9795c0jangwon.lee case MSG_SET_CLIENT: { 544b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav if (DEBUG) { 545eae626fd8c9ecb91c43ccb1dda050de52f9795c0jangwon.lee Log.i(LOG_TAG, "MSG_SET_CLIENT " 546b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav + getPackageName()); 547b5f180608db6de123b54ae94de569ff1ebca705cSvetoslav } 548269403b032f965ff3847eb982c2f697229dc5a92Svetoslav mClient = (IPrintServiceClient) message.obj; 549269403b032f965ff3847eb982c2f697229dc5a92Svetoslav if (mClient != null) { 5504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov onConnected(); 5514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } else { 5524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov onDisconnected(); 553269403b032f965ff3847eb982c2f697229dc5a92Svetoslav } 5544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } break; 5554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 5564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov default: { 5574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov throw new IllegalArgumentException("Unknown message: " + action); 5584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 5594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 5604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 5614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 5624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov} 563