PrintService.java revision 4b9a4d16872bbb50712e007b419ac0b35ff1582d
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.print.PrinterInfo;
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>
394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * This is the base class for implementing print services. A print service
404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * knows how to discover and interact one or more printers via one or more
414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * protocols.
424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p>
434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <h3>Printer discovery</h3>
444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p>
454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * A print service is responsible for discovering and reporting printers.
464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * A printer discovery period starts with a call to
474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * {@link #onStartPrinterDiscovery()} and ends with a call to
484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * {@link #onStopPrinterDiscovery()}. During a printer discovery
494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * period the print service reports newly discovered printers by
504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * calling {@link #addDiscoveredPrinters(List)} and added printers
514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * that disappeared by calling {@link #removeDiscoveredPrinters(List)}.
524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Calls to {@link #addDiscoveredPrinters(List)} and
534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * {@link #removeDiscoveredPrinters(List)} before a call to
544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * {@link #onStartPrinterDiscovery()} and after a call to
554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * {@link #onStopPrinterDiscovery()} is a no-op.
564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p>
574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p>
584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * For every printer discovery period all printers have to be added. Each
594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * printer known to this print service should be added only once during a
604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * discovery period, unless it was added and then removed before that.
614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Only an already added printer can be removed.
624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p>
634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <h3>Print jobs</h3>
644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p>
654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * When a new print job targeted to the printers managed by this print
664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * service is queued, i.e. ready for processing by the print service,
674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * a call to {@link #onPrintJobQueued(PrintJob)} is made and the print
684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * service may handle it immediately or schedule that for an appropriate
694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * time in the future. The list of all print jobs for this service
704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * are be available by calling {@link #getPrintJobs()}. A queued print
714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * job is in a {@link PrintJobInfo#STATE_QUEUED} state.
724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p>
734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p>
744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * A print service is responsible for setting the print job state as
754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * appropriate while processing it. Initially, a print job is in a
764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * {@link PrintJobInfo#STATE_QUEUED} state which means that the data to
774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * be printed is spooled by the system and the print service can obtain
784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * that data by calling {@link PrintJob#getData()}. After the print
794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * service starts printing the data it should set the print job state
804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * to {@link PrintJobInfo#STATE_STARTED}. Upon successful completion, the
814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * print job state has to be set to {@link PrintJobInfo#STATE_COMPLETED}.
824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * In a case of a failure, the print job state should be set to
834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * {@link PrintJobInfo#STATE_FAILED}. If a print job is in a
844b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * {@link PrintJobInfo#STATE_STARTED} state and the user requests to
854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * cancel it, the print service will receive a call to
864b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * {@link #onRequestCancelPrintJob(PrintJob)} which requests from the
874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * service to do a best effort in canceling the job. In case the job
884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * is successfully canceled, its state has to be set to
894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * {@link PrintJobInfo#STATE_CANCELED}.
904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p>
914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <h3>Lifecycle</h3>
924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p>
934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * The lifecycle of a print service is managed exclusively by the system
944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * and follows the established service lifecycle. Additionally, starting
954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * or stopping a print service is triggered exclusively by an explicit
964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * user action through enabling or disabling it in the device settings.
974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * After the system binds to a print service, it calls {@link #onConnected()}.
984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * This method can be overriden by clients to perform post binding setup.
994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Also after the system unbinds from a print service, it calls
1004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * {@link #onDisconnected()}. This method can be overriden by clients to
1014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * perform post unbinding cleanup.
1024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p>
1034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <h3>Declaration</h3>
1044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p>
1054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * A print service is declared as any other service in an AndroidManifest.xml
1064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * but it must also specify that it handles the {@link android.content.Intent}
1074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * with action {@link #SERVICE_INTERFACE}. Failure to declare this intent
1084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * will cause the system to ignore the print service. Additionally, a print
1094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * service must request the {@link android.Manifest.permission#BIND_PRINT_SERVICE}
1104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * permission to ensure that only the system can bind to it. Failure to
1114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * declare this intent will cause the system to ignore the print service.
1124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Following is an example declaration:
1134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p>
1144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <pre>
1154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * &lt;service android:name=".MyPrintService"
1164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov *         android:permission="android.permission.BIND_PRINT_SERVICE"&gt;
1174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov *     &lt;intent-filter&gt;
1184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov *         &lt;action android:name="android.printservice.PrintService" /&gt;
1194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov *     &lt;/intent-filter&gt;
1204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov *     . . .
1214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * &lt;/service&gt;
1224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </pre>
1234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <h3>Configuration</h3>
1244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p>
1254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * A print service can be configured by specifying an optional settings
1264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * activity which exposes service specific options, an optional add
1274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * prints activity which is used for manual addition of printers, etc.
1284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * It is a responsibility of the system to launch the settings and add
1294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * printers activities when appropriate.
1304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p>
1314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p>
1324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * A print service is configured by providing a
1334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * {@link #SERVICE_META_DATA meta-data} entry in the manifest when declaring
1344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * the service. A service declaration with a meta-data tag is presented
1354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * below:
1364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <pre> &lt;service android:name=".MyPrintService"
1374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov *         android:permission="android.permission.BIND_PRINT_SERVICE"&gt;
1384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov *     &lt;intent-filter&gt;
1394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov *         &lt;action android:name="android.printservice.PrintService" /&gt;
1404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov *     &lt;/intent-filter&gt;
1414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov *     &lt;meta-data android:name="android.printservice" android:resource="@xml/printservice" /&gt;
1424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * &lt;/service&gt;</pre>
1434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p>
1444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <p>
1454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * For more details refer to {@link #SERVICE_META_DATA} and
1464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * <code>&lt;{@link android.R.styleable#PrintService print-service}&gt;</code>.
1474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * </p>
1484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */
1494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovpublic abstract class PrintService extends Service {
1504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private static final String LOG_TAG = PrintService.class.getSimpleName();
1524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
1544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * The {@link Intent} action that must be declared as handled by a service
1554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * in its manifest to allow the system to recognize it as a print service.
1564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
1574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public static final String SERVICE_INTERFACE = "android.printservice.PrintService";
1584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
1604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Name under which a PrintService component publishes additional information
1614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * about itself. This meta-data must reference an XML resource containing a
1624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * <code>&lt;{@link android.R.styleable#PrintService print-service}&gt;</code>
1634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * tag. This is a a sample XML file configuring a print service:
1644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * <pre> &lt;print-service
1654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *     android:settingsActivity="foo.bar.MySettingsActivity"
1664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *     andorid:addPrintersActivity="foo.bar.MyAddPrintersActivity."
1674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *     . . .
1684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * /&gt;</pre>
1694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
1704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public static final String SERVICE_META_DATA = "android.printservice";
1714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private final Object mLock = new Object();
1734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private Handler mHandler;
1754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private IPrintServiceClient mClient;
1774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private boolean mDiscoveringPrinters;
1794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    @Override
1814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    protected void attachBaseContext(Context base) {
1824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        super.attachBaseContext(base);
1834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mHandler = new MyHandler(base.getMainLooper());
1844b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
1854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1864b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
1874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * The system has connected to this service.
1884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
1894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    protected void onConnected() {
1904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        /* do nothing */
1914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
1924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
1944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * The system has disconnected from this service.
1954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
1964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    protected void onDisconnected() {
1974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        /* do nothing */
1984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
1994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
2014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Callback requesting from this service to start printer discovery.
2024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * At the end of the printer discovery period the system will call
2034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * {@link #onStopPrinterDiscovery(). Discovered printers should be
2044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * reported by calling #addDiscoveredPrinters(List) and reported ones
2054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * that disappear should be reported by calling
2064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * {@link #removeDiscoveredPrinters(List)}.
2074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
2084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see #onStopPrinterDiscovery()
2094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see #addDiscoveredPrinters(List)
2104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see #removeDiscoveredPrinters(List)
2114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
2124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    protected abstract void onStartPrinterDiscovery();
2134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
2154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Callback requesting from this service to stop printer discovery.
2164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
2174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see #onStartPrinterDiscovery()
2184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see #addDiscoveredPrinters(List)
2194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see #removeDiscoveredPrinters(List)
2204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
2214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    protected abstract void onStopPrinterDiscovery();
2224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
2244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Adds discovered printers. This method should be called during a
2254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * printer discovery period, i.e. after a call to
2264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * {@link #onStartPrinterDiscovery()} and before the corresponding
2274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * call to {@link #onStopPrinterDiscovery()}, otherwise it does nothing.
2284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * <p>
2294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * <strong>Note:</strong> For every printer discovery period all
2304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * printers have to be added. You can call this method as many times as
2314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * necessary during the discovery period but should not pass in already
2324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * added printers. If a printer is already added in the same printer
2334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * discovery period, it will be ignored.
2344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * </p>
2354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
2364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @param printers A list with discovered printers.
2374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
2384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @throws IllegalStateException If this service is not connected.
2394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
2404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see #removeDiscoveredPrinters(List)
2414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see #onStartPrinterDiscovery()
2424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see #onStopPrinterDiscovery()
2434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
2444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public final void addDiscoveredPrinters(List<PrinterInfo> printers) {
2454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        synchronized (mLock) {
2464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (mClient == null) {
2474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throw new IllegalStateException("Print serivice not connected!");
2484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
2494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (mDiscoveringPrinters) {
2504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                try {
2514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    // Calling with a lock into the system is fine.
2524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    mClient.addDiscoveredPrinters(printers);
2534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                } catch (RemoteException re) {
2544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    Log.e(LOG_TAG, "Error adding discovered printers!", re);
2554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                }
2564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
2574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
2584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
2594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
2614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Removes discovered printers given their ids. This method should be called
2624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * during a printer discovery period, i.e. after a call to
2634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * {@link #onStartPrinterDiscovery()} and before the corresponding
2644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * call to {@link #onStopPrinterDiscovery()}, otherwise it does nothing.
2654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * <p>
2664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * For every printer discovery period all printers have to be added. You
2674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * should remove only printers that were added in this printer discovery
2684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * period by a call to {@link #addDiscoveredPrinters(List)}. You can call
2694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * this method as many times as necessary during the discovery period
2704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * but should not pass in already removed printer ids. If a printer with
2714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * a given id is already removed in the same discovery period, it will
2724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * be ignored.
2734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * </p>
2744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
2754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @param printerIds A list with disappeared printer ids.
2764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
2774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @throws IllegalStateException If this service is not connected.
2784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
2794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see #addDiscoveredPrinters(List)
2804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see #onStartPrinterDiscovery()
2814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see #onStopPrinterDiscovery()
2824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
2834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public final void removeDiscoveredPrinters(List<PrinterId> printerIds) {
2844b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        synchronized (mLock) {
2854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (mClient == null) {
2864b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throw new IllegalStateException("Print serivice not connected!");
2874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
2884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (mDiscoveringPrinters) {
2894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                try {
2904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    // Calling with a lock into the system is fine.
2914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    mClient.removeDiscoveredPrinters(printerIds);
2924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                } catch (RemoteException re) {
2934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    Log.e(LOG_TAG, "Error removing discovered printers!", re);
2944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                }
2954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
2964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
2974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
2984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
2994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
3004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Called when canceling of a print job is requested. The service
3014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * should do best effort to fulfill the request. After the print
3024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * job is canceled it state has to be set to
3034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * {@link PrintJobInfo#STATE_CANCELED}.
3044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
3054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @param printJob The print job to be canceled.
3064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
3074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    protected void onRequestCancelPrintJob(PrintJob printJob) {
3084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
3094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
3104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
3114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Called when there is a queued print job for one of the printers
3124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * managed by this print service. A queued print job is ready for
3134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * processing by a print service which can get the data to be printed
3144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * by calling {@link PrintJob#getData()}. This service may start
3154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * processing the passed in print job or schedule handling of queued
3164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * print jobs at a convenient time. The service can get the print
3174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * jobs by a call to {@link #getPrintJobs()} and examine their state
3184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * to find the ones with state {@link PrintJobInfo#STATE_QUEUED}.
3194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
3204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @param printJob The new queued print job.
3214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
3224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @see #getPrintJobs()
3234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
3244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    protected abstract void onPrintJobQueued(PrintJob printJob);
3254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
3264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
3274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Gets the print jobs for the printers managed by this service.
3284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
3294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @return The print jobs.
3304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
3314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @throws IllegalStateException If this service is not connected.
3324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
3334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public final List<PrintJob> getPrintJobs() {
3344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        synchronized (mLock) {
3354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            if (mClient == null) {
3364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                throw new IllegalStateException("Print serivice not connected!");
3374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
3384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            try {
3394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                List<PrintJob> printJobs = null;
3404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                List<PrintJobInfo> printJobInfos = mClient.getPrintJobs();
3414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                if (printJobInfos != null) {
3424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    final int printJobInfoCount = printJobInfos.size();
3434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    printJobs = new ArrayList<PrintJob>(printJobInfoCount);
3444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    for (int i = 0; i < printJobInfoCount; i++) {
3454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                        printJobs.add(new PrintJob(printJobInfos.get(i), mClient));
3464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    }
3474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                }
3484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                if (printJobs != null) {
3494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    return printJobs;
3504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                }
3514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            } catch (RemoteException re) {
3524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                Log.e(LOG_TAG, "Error calling getPrintJobs()", re);
3534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
3544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return Collections.emptyList();
3554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
3564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
3574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
3584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    /**
3594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * Generates a global printer id from a local id. The local id is unique
3604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * only within this print service.
3614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     *
3624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @param localId The local id.
3634b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     * @return Global printer id.
3644b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov     */
3654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public final PrinterId generatePrinterId(String localId) {
3664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return new PrinterId(new ComponentName(getPackageName(),
3674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                getClass().getName()), localId);
3684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
3694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
3704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    @Override
3714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    public final IBinder onBind(Intent intent) {
3724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        return new IPrintService.Stub() {
3734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            @Override
3744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            public void setClient(IPrintServiceClient client) {
3754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                mHandler.obtainMessage(MyHandler.MESSAGE_SET_CLEINT, client).sendToTarget();
3764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
3774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
3784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            @Override
3794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            public void startPrinterDiscovery() {
3804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                mHandler.sendEmptyMessage(MyHandler.MESSAGE_START_PRINTER_DISCOVERY);
3814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
3824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
3834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            @Override
3844b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            public void stopPrinterDiscovery() {
3854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                mHandler.sendEmptyMessage(MyHandler.MESSAGE_STOP_PRINTER_DISCOVERY);
3864b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
3874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
3884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            @Override
3894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            public void requestCancelPrintJob(PrintJobInfo printJob) {
3904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                mHandler.obtainMessage(MyHandler.MESSAGE_CANCEL_PRINTJOB, printJob).sendToTarget();
3914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
3924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
3934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            @Override
3944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            public void onPrintJobQueued(PrintJobInfo printJob) {
3954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                mHandler.obtainMessage(MyHandler.MESSAGE_ON_PRINTJOB_QUEUED,
3964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                        printJob).sendToTarget();
3974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
3984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        };
3994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
4004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
4014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private final class MyHandler extends Handler {
4024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public static final int MESSAGE_START_PRINTER_DISCOVERY = 1;
4034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public static final int MESSAGE_STOP_PRINTER_DISCOVERY = 2;
4044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public static final int MESSAGE_CANCEL_PRINTJOB = 3;
4054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public static final int MESSAGE_ON_PRINTJOB_QUEUED = 4;
4064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public static final int MESSAGE_SET_CLEINT = 5;
4074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
4084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public MyHandler(Looper looper) {
4094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            super(looper, null, true);
4104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
4114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
4124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        @Override
4134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public void handleMessage(Message message) {
4144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            final int action = message.what;
4154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            switch (action) {
4164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                case MESSAGE_START_PRINTER_DISCOVERY: {
4174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    synchronized (mLock) {
4184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                        mDiscoveringPrinters = true;
4194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    }
4204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    onStartPrinterDiscovery();
4214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                } break;
4224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
4234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                case MESSAGE_STOP_PRINTER_DISCOVERY: {
4244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    synchronized (mLock) {
4254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                        mDiscoveringPrinters = false;
4264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    }
4274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    onStopPrinterDiscovery();
4284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                } break;
4294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
4304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                case MESSAGE_CANCEL_PRINTJOB: {
4314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    PrintJobInfo printJob = (PrintJobInfo) message.obj;
4324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    onRequestCancelPrintJob(new PrintJob(printJob, mClient));
4334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                } break;
4344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
4354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                case MESSAGE_ON_PRINTJOB_QUEUED: {
4364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    PrintJobInfo printJob = (PrintJobInfo) message.obj;
4374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    onPrintJobQueued(new PrintJob(printJob, mClient));
4384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                } break;
4394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
4404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                case MESSAGE_SET_CLEINT: {
4414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    IPrintServiceClient client = (IPrintServiceClient) message.obj;
4424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    synchronized (mLock) {
4434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                        mClient = client;
4444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                        if (client == null) {
4454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                            mDiscoveringPrinters = false;
4464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                        }
4474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    }
4484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    if (client != null) {
4494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                        onConnected();
4504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                     } else {
4514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                        onStopPrinterDiscovery();
4524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                        onDisconnected();
4534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    }
4544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                } break;
4554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
4564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                default: {
4574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    throw new IllegalArgumentException("Unknown message: " + action);
4584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                }
4594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
4604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
4614b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
4624b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov}
463