NsdManager.java revision 6c07ba8183edc593527335238a2c6083392df7bc
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.net.nsd;
18
19import android.annotation.SdkConstant;
20import android.annotation.SdkConstant.SdkConstantType;
21import android.content.Context;
22import android.os.Binder;
23import android.os.IBinder;
24import android.os.Handler;
25import android.os.Looper;
26import android.os.Message;
27import android.os.RemoteException;
28import android.os.Messenger;
29import android.text.TextUtils;
30import android.util.Log;
31
32import com.android.internal.util.AsyncChannel;
33import com.android.internal.util.Protocol;
34
35/**
36 * The Network Service Discovery Manager class provides the API to discover services
37 * on a network. As an example, if device A and device B are connected over a Wi-Fi
38 * network, a game registered on device A can be discovered by a game on device
39 * B. Another example use case is an application discovering printers on the network.
40 *
41 * <p> The API currently supports DNS based service discovery and discovery is currently
42 * limited to a local network over Multicast DNS. In future, it will be extended to
43 * support wide area discovery and other service discovery mechanisms.
44 * DNS service discovery is described at http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt
45 *
46 * <p> The API is asynchronous and responses to requests from an application are on listener
47 * callbacks provided by the application. The application must invoke {@link #initialize} before
48 * doing any other operation.
49 *
50 * <p> There are three main operations the API supports - registration, discovery and resolution.
51 * <pre>
52 *                          Application start
53 *                                 |
54 *                                 |         <----------------------------------------------
55 *                             initialize()                                                 |
56 *                                 |                                                        |
57 *                                 | Wait until channel connects                            |
58 *                                 | before doing any operation                             |
59 *                                 |                                                        |
60 *                           onChannelConnected()                    __________             |
61 *                                 |                                           |            |
62 *                                 |                                           |            |
63 *                                 |                  onServiceRegistered()    |            |
64 *                     Register any local services  /                          |            |
65 *                      to be advertised with       \                          |            | If application needs to
66 *                       registerService()            onFailure()              |            | do any further operations
67 *                                 |                                           |            | again, it needs to
68 *                                 |                                           |            | initialize() connection
69 *                          discoverServices()                                 |            | to framework again
70 *                                 |                                           |            |
71 *                      Maintain a list to track                               |            |
72 *                        discovered services                                  |            |
73 *                                 |                                           |            |
74 *                                 |--------->                                 |-> onChannelDisconnected()
75 *                                 |          |                                |
76 *                                 |      onServiceFound()                     |
77 *                                 |          |                                |
78 *                                 |     add service to list                   |
79 *                                 |          |                                |
80 *                                 |<----------                                |
81 *                                 |                                           |
82 *                                 |--------->                                 |
83 *                                 |          |                                |
84 *                                 |      onServiceLost()                      |
85 *                                 |          |                                |
86 *                                 |   remove service from list                |
87 *                                 |          |                                |
88 *                                 |<----------                                |
89 *                                 |                                           |
90 *                                 |                                           |
91 *                                 | Connect to a service                      |
92 *                                 | from list ?                               |
93 *                                 |                                           |
94 *                          resolveService()                                   |
95 *                                 |                                           |
96 *                         onServiceResolved()                                 |
97 *                                 |                                           |
98 *                     Establish connection to service                         |
99 *                     with the host and port information                      |
100 *                                 |                                           |
101 *                                 |                                ___________|
102 *                           deinitialize()
103 *                    when done with all operations
104 *                          or before quit
105 *
106 * </pre>
107 * An application that needs to advertise itself over a network for other applications to
108 * discover it can do so with a call to {@link #registerService}. If Example is a http based
109 * application that can provide HTML data to peer services, it can register a name "Example"
110 * with service type "_http._tcp". A successful registration is notified with a callback to
111 * {@link DnsSdRegisterListener#onServiceRegistered} and a failure to register is notified
112 * over {@link DnsSdRegisterListener#onFailure}
113 *
114 * <p> A peer application looking for http services can initiate a discovery for "_http._tcp"
115 * with a call to {@link #discoverServices}. A service found is notified with a callback
116 * to {@link DnsSdDiscoveryListener#onServiceFound} and a service lost is notified on
117 * {@link DnsSdDiscoveryListener#onServiceLost}.
118 *
119 * <p> Once the peer application discovers the "Example" http srevice, and needs to receive data
120 * from the "Example" application, it can initiate a resolve with {@link #resolveService} to
121 * resolve the host and port details for the purpose of establishing a connection. A successful
122 * resolve is notified on {@link DnsSdResolveListener#onServiceResolved} and a failure is notified
123 * on {@link DnsSdResolveListener#onFailure}.
124 *
125 * Applications can reserve for a service type at
126 * http://www.iana.org/form/ports-service. Existing services can be found at
127 * http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml
128 *
129 * Get an instance of this class by calling {@link android.content.Context#getSystemService(String)
130 * Context.getSystemService(Context.NSD_SERVICE)}.
131 *
132 * {@see DnsSdServiceInfo}
133 */
134public class NsdManager {
135    private static final String TAG = "NsdManager";
136    INsdManager mService;
137
138    /**
139     * Broadcast intent action to indicate whether network service discovery is
140     * enabled or disabled. An extra {@link #EXTRA_NSD_STATE} provides the state
141     * information as int.
142     *
143     * @see #EXTRA_NSD_STATE
144     */
145    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
146    public static final String ACTION_NSD_STATE_CHANGED =
147        "android.net.nsd.STATE_CHANGED";
148
149    /**
150     * The lookup key for an int that indicates whether network service discovery is enabled
151     * or disabled. Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}.
152     *
153     * @see #NSD_STATE_DISABLED
154     * @see #NSD_STATE_ENABLED
155     */
156    public static final String EXTRA_NSD_STATE = "nsd_state";
157
158    /**
159     * Network service discovery is disabled
160     *
161     * @see #NSD_STATE_CHANGED_ACTION
162     */
163    public static final int NSD_STATE_DISABLED = 1;
164
165    /**
166     * Network service discovery is enabled
167     *
168     * @see #NSD_STATE_CHANGED_ACTION
169     */
170    public static final int NSD_STATE_ENABLED = 2;
171
172    private static final int BASE = Protocol.BASE_NSD_MANAGER;
173
174    /** @hide */
175    public static final int DISCOVER_SERVICES                       = BASE + 1;
176    /** @hide */
177    public static final int DISCOVER_SERVICES_STARTED               = BASE + 2;
178    /** @hide */
179    public static final int DISCOVER_SERVICES_FAILED                = BASE + 3;
180    /** @hide */
181    public static final int SERVICE_FOUND                           = BASE + 4;
182    /** @hide */
183    public static final int SERVICE_LOST                            = BASE + 5;
184
185    /** @hide */
186    public static final int STOP_DISCOVERY                          = BASE + 6;
187    /** @hide */
188    public static final int STOP_DISCOVERY_FAILED                   = BASE + 7;
189    /** @hide */
190    public static final int STOP_DISCOVERY_SUCCEEDED                = BASE + 8;
191
192    /** @hide */
193    public static final int REGISTER_SERVICE                        = BASE + 9;
194    /** @hide */
195    public static final int REGISTER_SERVICE_FAILED                 = BASE + 10;
196    /** @hide */
197    public static final int REGISTER_SERVICE_SUCCEEDED              = BASE + 11;
198
199    /** @hide */
200    public static final int UNREGISTER_SERVICE                      = BASE + 12;
201    /** @hide */
202    public static final int UNREGISTER_SERVICE_FAILED               = BASE + 13;
203    /** @hide */
204    public static final int UNREGISTER_SERVICE_SUCCEEDED            = BASE + 14;
205
206    /** @hide */
207    public static final int UPDATE_SERVICE                          = BASE + 15;
208    /** @hide */
209    public static final int UPDATE_SERVICE_FAILED                   = BASE + 16;
210    /** @hide */
211    public static final int UPDATE_SERVICE_SUCCEEDED                = BASE + 17;
212
213    /** @hide */
214    public static final int RESOLVE_SERVICE                         = BASE + 18;
215    /** @hide */
216    public static final int RESOLVE_SERVICE_FAILED                  = BASE + 19;
217    /** @hide */
218    public static final int RESOLVE_SERVICE_SUCCEEDED               = BASE + 20;
219
220    /** @hide */
221    public static final int STOP_RESOLVE                            = BASE + 21;
222    /** @hide */
223    public static final int STOP_RESOLVE_FAILED                     = BASE + 22;
224    /** @hide */
225    public static final int STOP_RESOLVE_SUCCEEDED                  = BASE + 23;
226
227    /** @hide */
228    public static final int ENABLE                                  = BASE + 24;
229    /** @hide */
230    public static final int DISABLE                                 = BASE + 25;
231
232
233    /**
234     * Create a new Nsd instance. Applications use
235     * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
236     * {@link android.content.Context#NSD_SERVICE Context.NSD_SERVICE}.
237     * @param service the Binder interface
238     * @hide - hide this because it takes in a parameter of type INsdManager, which
239     * is a system private class.
240     */
241    public NsdManager(INsdManager service) {
242        mService = service;
243    }
244
245    /**
246     * Passed with onFailure() calls.
247     * Indicates that the operation failed due to an internal error.
248     */
249    public static final int ERROR               = 0;
250
251    /**
252     * Passed with onFailure() calls.
253     * Indicates that the operation failed because service discovery
254     * is unsupported on the device.
255     */
256    public static final int UNSUPPORTED         = 1;
257
258    /**
259     * Passed with onFailure() calls.
260     * Indicates that the operation failed because the framework is
261     * busy and unable to service the request.
262     */
263    public static final int BUSY                = 2;
264
265    /**
266     * Passed with onFailure() calls.
267     * Indicates that the operation failed because it is already active.
268     */
269    public static final int ALREADY_ACTIVE      = 3;
270
271    /**
272     * Passed with onFailure() calls.
273     * Indicates that the operation failed because maximum limit on
274     * service registrations has reached.
275     */
276    public static final int MAX_REGS_REACHED    = 4;
277
278    /** Interface for callback invocation when framework channel is connected or lost */
279    public interface ChannelListener {
280       /**
281         * The channel to the framework is connected.
282         * Application can initiate calls into the framework using the channel instance passed.
283         */
284        public void onChannelConnected(Channel c);
285        /**
286         * The channel to the framework has been disconnected.
287         * Application could try re-initializing using {@link #initialize}
288         */
289        public void onChannelDisconnected();
290    }
291
292    /** Generic interface for callback invocation for a success or failure */
293    public interface ActionListener {
294
295        public void onFailure(int errorCode);
296
297        public void onSuccess();
298    }
299
300    /** Interface for callback invocation for service discovery */
301    public interface DnsSdDiscoveryListener {
302
303        public void onFailure(int errorCode);
304
305        public void onStarted(String serviceType);
306
307        public void onServiceFound(DnsSdServiceInfo serviceInfo);
308
309        public void onServiceLost(DnsSdServiceInfo serviceInfo);
310
311    }
312
313    /** Interface for callback invocation for service registration */
314    public interface DnsSdRegisterListener {
315
316        public void onFailure(int errorCode);
317
318        public void onServiceRegistered(int registeredId, DnsSdServiceInfo serviceInfo);
319    }
320
321    /** @hide */
322    public interface DnsSdUpdateRegistrationListener {
323
324        public void onFailure(int errorCode);
325
326        public void onServiceUpdated(int registeredId, DnsSdTxtRecord txtRecord);
327    }
328
329    /** Interface for callback invocation for service resolution */
330    public interface DnsSdResolveListener {
331
332        public void onFailure(int errorCode);
333
334        public void onServiceResolved(DnsSdServiceInfo serviceInfo);
335    }
336
337    /**
338     * A channel that connects the application to the NetworkService framework.
339     * Most service operations require a Channel as an argument. An instance of Channel is obtained
340     * by doing a call on {@link #initialize}
341     */
342    public static class Channel {
343        Channel(Looper looper, ChannelListener l) {
344            mAsyncChannel = new AsyncChannel();
345            mHandler = new ServiceHandler(looper);
346            mChannelListener = l;
347        }
348        private ChannelListener mChannelListener;
349        private DnsSdDiscoveryListener mDnsSdDiscoveryListener;
350        private ActionListener mDnsSdStopDiscoveryListener;
351        private DnsSdRegisterListener mDnsSdRegisterListener;
352        private ActionListener mDnsSdUnregisterListener;
353        private DnsSdUpdateRegistrationListener mDnsSdUpdateListener;
354        private DnsSdResolveListener mDnsSdResolveListener;
355        private ActionListener mDnsSdStopResolveListener;
356
357        private AsyncChannel mAsyncChannel;
358        private ServiceHandler mHandler;
359        class ServiceHandler extends Handler {
360            ServiceHandler(Looper looper) {
361                super(looper);
362            }
363
364            @Override
365            public void handleMessage(Message message) {
366                switch (message.what) {
367                    case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
368                        mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
369                        break;
370                    case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
371                        if (mChannelListener != null) {
372                            mChannelListener.onChannelConnected(Channel.this);
373                        }
374                        break;
375                    case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
376                        if (mChannelListener != null) {
377                            mChannelListener.onChannelDisconnected();
378                            mChannelListener = null;
379                        }
380                        break;
381                    case DISCOVER_SERVICES_STARTED:
382                        if (mDnsSdDiscoveryListener != null) {
383                            mDnsSdDiscoveryListener.onStarted((String) message.obj);
384                        }
385                        break;
386                    case DISCOVER_SERVICES_FAILED:
387                        if (mDnsSdDiscoveryListener != null) {
388                            mDnsSdDiscoveryListener.onFailure(message.arg1);
389                        }
390                        break;
391                    case SERVICE_FOUND:
392                        if (mDnsSdDiscoveryListener != null) {
393                            mDnsSdDiscoveryListener.onServiceFound(
394                                    (DnsSdServiceInfo) message.obj);
395                        }
396                        break;
397                    case SERVICE_LOST:
398                        if (mDnsSdDiscoveryListener != null) {
399                            mDnsSdDiscoveryListener.onServiceLost(
400                                    (DnsSdServiceInfo) message.obj);
401                        }
402                        break;
403                    case STOP_DISCOVERY_FAILED:
404                        if (mDnsSdStopDiscoveryListener != null) {
405                            mDnsSdStopDiscoveryListener.onFailure(message.arg1);
406                        }
407                        break;
408                    case STOP_DISCOVERY_SUCCEEDED:
409                        if (mDnsSdStopDiscoveryListener != null) {
410                            mDnsSdStopDiscoveryListener.onSuccess();
411                        }
412                        break;
413                    case REGISTER_SERVICE_FAILED:
414                        if (mDnsSdRegisterListener != null) {
415                            mDnsSdRegisterListener.onFailure(message.arg1);
416                        }
417                        break;
418                    case REGISTER_SERVICE_SUCCEEDED:
419                        if (mDnsSdRegisterListener != null) {
420                            mDnsSdRegisterListener.onServiceRegistered(message.arg1,
421                                    (DnsSdServiceInfo) message.obj);
422                        }
423                        break;
424                    case UNREGISTER_SERVICE_FAILED:
425                        if (mDnsSdUnregisterListener != null) {
426                            mDnsSdUnregisterListener.onFailure(message.arg1);
427                        }
428                        break;
429                    case UNREGISTER_SERVICE_SUCCEEDED:
430                        if (mDnsSdUnregisterListener != null) {
431                            mDnsSdUnregisterListener.onSuccess();
432                        }
433                        break;
434                   case UPDATE_SERVICE_FAILED:
435                        if (mDnsSdUpdateListener != null) {
436                            mDnsSdUpdateListener.onFailure(message.arg1);
437                        }
438                        break;
439                    case UPDATE_SERVICE_SUCCEEDED:
440                        if (mDnsSdUpdateListener != null) {
441                            mDnsSdUpdateListener.onServiceUpdated(message.arg1,
442                                    (DnsSdTxtRecord) message.obj);
443                        }
444                        break;
445                    case RESOLVE_SERVICE_FAILED:
446                        if (mDnsSdResolveListener != null) {
447                            mDnsSdResolveListener.onFailure(message.arg1);
448                        }
449                        break;
450                    case RESOLVE_SERVICE_SUCCEEDED:
451                        if (mDnsSdResolveListener != null) {
452                            mDnsSdResolveListener.onServiceResolved(
453                                    (DnsSdServiceInfo) message.obj);
454                        }
455                        break;
456                    case STOP_RESOLVE_FAILED:
457                        if (mDnsSdStopResolveListener!= null) {
458                            mDnsSdStopResolveListener.onFailure(message.arg1);
459                        }
460                        break;
461                    case STOP_RESOLVE_SUCCEEDED:
462                        if (mDnsSdStopResolveListener != null) {
463                            mDnsSdStopResolveListener.onSuccess();
464                        }
465                        break;
466                    default:
467                        Log.d(TAG, "Ignored " + message);
468                        break;
469                }
470            }
471        }
472   }
473
474    private static void checkChannel(Channel c) {
475        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
476    }
477
478    /**
479     * Registers the application with the service discovery framework. This function
480     * must be the first to be called before any other operations are performed. No service
481     * discovery operations must be performed until the ChannelListener callback notifies
482     * that the channel is connected
483     *
484     * @param srcContext is the context of the source
485     * @param srcLooper is the Looper on which the callbacks are receivied
486     * @param listener for callback at loss of framework communication. Cannot be null.
487     */
488    public void initialize(Context srcContext, Looper srcLooper, ChannelListener listener) {
489        Messenger messenger = getMessenger();
490        if (messenger == null) throw new RuntimeException("Failed to initialize");
491        if (listener == null) throw new IllegalArgumentException("ChannelListener cannot be null");
492
493        Channel c = new Channel(srcLooper, listener);
494        c.mAsyncChannel.connect(srcContext, c.mHandler, messenger);
495    }
496
497    /**
498     * Disconnects application from service discovery framework. No further operations
499     * will succeed until a {@link #initialize} is called again.
500     *
501     * @param c channel initialized with {@link #initialize}
502     */
503    public void deinitialize(Channel c) {
504        checkChannel(c);
505        c.mAsyncChannel.disconnect();
506    }
507
508    /**
509     * Register a service to be discovered by other services.
510     *
511     * <p> The function call immediately returns after sending a request to register service
512     * to the framework. The application is notified of a success to initiate
513     * discovery through the callback {@link DnsSdRegisterListener#onServiceRegistered} or a failure
514     * through {@link DnsSdRegisterListener#onFailure}.
515     *
516     * @param c is the channel created at {@link #initialize}
517     * @param serviceType The service type being advertised.
518     * @param port on which the service is listenering for incoming connections
519     * @param listener for success or failure callback. Can be null.
520     */
521    public void registerService(Channel c, String serviceName, String serviceType, int port,
522            DnsSdRegisterListener listener) {
523        checkChannel(c);
524        if (TextUtils.isEmpty(serviceName) || TextUtils.isEmpty(serviceType)) {
525            throw new IllegalArgumentException("Service name or type cannot be empty");
526        }
527        if (port <= 0) {
528            throw new IllegalArgumentException("Invalid port number");
529        }
530        DnsSdServiceInfo serviceInfo = new DnsSdServiceInfo(serviceName, serviceType, null);
531        serviceInfo.setPort(port);
532        c.mDnsSdRegisterListener = listener;
533        c.mAsyncChannel.sendMessage(REGISTER_SERVICE, serviceInfo);
534    }
535
536    /**
537     * Unregister a service registered through {@link #registerService}
538     * @param c is the channel created at {@link #initialize}
539     * @param registeredId is obtained at {@link DnsSdRegisterListener#onServiceRegistered}
540     * @param listener provides callbacks for success or failure. Can be null.
541     */
542    public void unregisterService(Channel c, int registeredId, ActionListener listener) {
543        checkChannel(c);
544        c.mDnsSdUnregisterListener = listener;
545        c.mAsyncChannel.sendMessage(UNREGISTER_SERVICE, registeredId);
546    }
547
548    /** @hide */
549    public void updateService(Channel c, int registeredId, DnsSdTxtRecord txtRecord) {
550        checkChannel(c);
551        c.mAsyncChannel.sendMessage(UPDATE_SERVICE, registeredId, 0, txtRecord);
552    }
553
554    /**
555     * Initiate service discovery to browse for instances of a service type. Service discovery
556     * consumes network bandwidth and will continue until the application calls
557     * {@link #stopServiceDiscovery}.
558     *
559     * <p> The function call immediately returns after sending a request to start service
560     * discovery to the framework. The application is notified of a success to initiate
561     * discovery through the callback {@link DnsSdDiscoveryListener#onStarted} or a failure
562     * through {@link DnsSdDiscoveryListener#onFailure}.
563     *
564     * <p> Upon successful start, application is notified when a service is found with
565     * {@link DnsSdDiscoveryListener#onServiceFound} or when a service is lost with
566     * {@link DnsSdDiscoveryListener#onServiceLost}.
567     *
568     * <p> Upon failure to start, service discovery is not active and application does
569     * not need to invoke {@link #stopServiceDiscovery}
570     *
571     * @param c is the channel created at {@link #initialize}
572     * @param serviceType The service type being discovered. Examples include "_http._tcp" for
573     * http services or "_ipp._tcp" for printers
574     * @param listener provides callbacks when service is found or lost. Cannot be null.
575     */
576    public void discoverServices(Channel c, String serviceType, DnsSdDiscoveryListener listener) {
577        checkChannel(c);
578        if (listener == null) {
579            throw new IllegalStateException("Discovery listener needs to be set first");
580        }
581        if (TextUtils.isEmpty(serviceType)) {
582            throw new IllegalStateException("Service type cannot be empty");
583        }
584        DnsSdServiceInfo s = new DnsSdServiceInfo();
585        s.setServiceType(serviceType);
586        c.mDnsSdDiscoveryListener = listener;
587        c.mAsyncChannel.sendMessage(DISCOVER_SERVICES, s);
588    }
589
590    /**
591     * Stop service discovery initiated with {@link #discoverServices}. An active service
592     * discovery is notified to the application with {@link DnsSdDiscoveryListener#onStarted}
593     * and it stays active until the application invokes a stop service discovery.
594     *
595     * <p> Upon failure to start service discovery notified through
596     * {@link DnsSdDiscoveryListener#onFailure} service discovery is not active and
597     * application does not need to stop it.
598     *
599     * @param c is the channel created at {@link #initialize}
600     * @param listener notifies success or failure. Can be null.
601     */
602    public void stopServiceDiscovery(Channel c, ActionListener listener) {
603        checkChannel(c);
604        c.mDnsSdStopDiscoveryListener = listener;
605        c.mAsyncChannel.sendMessage(STOP_DISCOVERY);
606    }
607
608    /**
609     * Resolve a discovered service. An application can resolve a service right before
610     * establishing a connection to fetch the IP and port details on which to setup
611     * the connection.
612     *
613     * @param c is the channel created at {@link #initialize}
614     * @param serviceName of the the service
615     * @param serviceType of the service
616     * @param listener to receive callback upon success or failure. Cannot be null.
617     */
618    public void resolveService(Channel c, String serviceName, String serviceType,
619            DnsSdResolveListener listener) {
620        checkChannel(c);
621        if (TextUtils.isEmpty(serviceName) || TextUtils.isEmpty(serviceType)) {
622            throw new IllegalArgumentException("Service name or type cannot be empty");
623        }
624        if (listener == null) throw new
625                IllegalStateException("Resolve listener cannot be null");
626        c.mDnsSdResolveListener = listener;
627        DnsSdServiceInfo serviceInfo = new DnsSdServiceInfo(serviceName, serviceType, null);
628        c.mAsyncChannel.sendMessage(RESOLVE_SERVICE, serviceInfo);
629    }
630
631    /** @hide */
632    public void stopServiceResolve(Channel c) {
633        checkChannel(c);
634        if (c.mDnsSdResolveListener == null) throw new
635                IllegalStateException("Resolve listener needs to be set first");
636        c.mAsyncChannel.sendMessage(STOP_RESOLVE);
637    }
638
639    /** Internal use only @hide */
640    public void setEnabled(boolean enabled) {
641        try {
642            mService.setEnabled(enabled);
643        } catch (RemoteException e) { }
644    }
645
646    /**
647     * Get a reference to NetworkService handler. This is used to establish
648     * an AsyncChannel communication with the service
649     *
650     * @return Messenger pointing to the NetworkService handler
651     */
652    private Messenger getMessenger() {
653        try {
654            return mService.getMessenger();
655        } catch (RemoteException e) {
656            return null;
657        }
658    }
659}
660