NsdManager.java revision 3fc376b7336cfbddbb10ce3f93a853a927f6513a
17d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff/* 27d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * Copyright (C) 2012 The Android Open Source Project 37d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * 47d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * Licensed under the Apache License, Version 2.0 (the "License"); 57d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * you may not use this file except in compliance with the License. 67d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * You may obtain a copy of the License at 77d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * 87d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * http://www.apache.org/licenses/LICENSE-2.0 97d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * 107d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * Unless required by applicable law or agreed to in writing, software 117d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * distributed under the License is distributed on an "AS IS" BASIS, 127d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * See the License for the specific language governing permissions and 147d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * limitations under the License. 157d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff */ 167d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 177d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffpackage android.net.nsd; 187d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 193ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriffimport android.annotation.SdkConstant; 203ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriffimport android.annotation.SdkConstant.SdkConstantType; 217d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport android.content.Context; 227d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport android.os.Binder; 237d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport android.os.IBinder; 247d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport android.os.Handler; 2522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriffimport android.os.HandlerThread; 267d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport android.os.Looper; 277d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport android.os.Message; 287d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport android.os.RemoteException; 297d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport android.os.Messenger; 3092784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriffimport android.text.TextUtils; 317d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport android.util.Log; 3222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriffimport android.util.SparseArray; 3322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 3422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriffimport java.util.concurrent.CountDownLatch; 357d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 367d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport com.android.internal.util.AsyncChannel; 377d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport com.android.internal.util.Protocol; 387d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 397d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff/** 4092784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * The Network Service Discovery Manager class provides the API to discover services 4192784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * on a network. As an example, if device A and device B are connected over a Wi-Fi 4292784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * network, a game registered on device A can be discovered by a game on device 4392784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * B. Another example use case is an application discovering printers on the network. 4492784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * 4592784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * <p> The API currently supports DNS based service discovery and discovery is currently 4622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * limited to a local network over Multicast DNS. DNS service discovery is described at 4722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt 487d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * 497d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * <p> The API is asynchronous and responses to requests from an application are on listener 5022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * callbacks on a seperate thread. 5192784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * 5292784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * <p> There are three main operations the API supports - registration, discovery and resolution. 5392784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * <pre> 5492784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * Application start 5592784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * | 5622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | 5722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | onServiceRegistered() 5822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * Register any local services / 5922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * to be advertised with \ 6022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * registerService() onRegistrationFailed() 6122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | 6222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | 6322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * discoverServices() 6422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | 6522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * Maintain a list to track 6622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * discovered services 6722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | 6822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * |---------> 6922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | | 7022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | onServiceFound() 7122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | | 7222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | add service to list 7322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | | 7422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * |<---------- 7522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | 7622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * |---------> 7722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | | 7822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | onServiceLost() 7922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | | 8022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | remove service from list 8122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | | 8222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * |<---------- 8322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | 8422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | 8522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | Connect to a service 8622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | from list ? 8722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | 8822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * resolveService() 8922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | 9022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * onServiceResolved() 9122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * | 9222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * Establish connection to service 9322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * with the host and port information 9492784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * 9592784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * </pre> 9692784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * An application that needs to advertise itself over a network for other applications to 9792784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * discover it can do so with a call to {@link #registerService}. If Example is a http based 9892784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * application that can provide HTML data to peer services, it can register a name "Example" 9992784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * with service type "_http._tcp". A successful registration is notified with a callback to 10022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * {@link RegistrationListener#onServiceRegistered} and a failure to register is notified 10122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * over {@link RegistrationListener#onRegistrationFailed} 10292784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * 10392784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * <p> A peer application looking for http services can initiate a discovery for "_http._tcp" 10492784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * with a call to {@link #discoverServices}. A service found is notified with a callback 10522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * to {@link DiscoveryListener#onServiceFound} and a service lost is notified on 10622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * {@link DiscoveryListener#onServiceLost}. 10792784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * 10892784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * <p> Once the peer application discovers the "Example" http srevice, and needs to receive data 10992784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * from the "Example" application, it can initiate a resolve with {@link #resolveService} to 11092784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * resolve the host and port details for the purpose of establishing a connection. A successful 11122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * resolve is notified on {@link ResolveListener#onServiceResolved} and a failure is notified 11222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * on {@link ResolveListener#onResolveFailed}. 1137d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * 11492784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * Applications can reserve for a service type at 11592784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * http://www.iana.org/form/ports-service. Existing services can be found at 11692784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml 1177d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * 1187d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * Get an instance of this class by calling {@link android.content.Context#getSystemService(String) 1197d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * Context.getSystemService(Context.NSD_SERVICE)}. 1207d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * 12122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * {@see NsdServiceInfo} 1227d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff */ 12322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriffpublic final class NsdManager { 1247d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff private static final String TAG = "NsdManager"; 1257d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff INsdManager mService; 1267d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 1273ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff /** 1283ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff * Broadcast intent action to indicate whether network service discovery is 1293ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff * enabled or disabled. An extra {@link #EXTRA_NSD_STATE} provides the state 1303ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff * information as int. 1313ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff * 1323ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff * @see #EXTRA_NSD_STATE 1333ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff */ 1343ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1356c07ba8183edc593527335238a2c6083392df7bcIrfan Sheriff public static final String ACTION_NSD_STATE_CHANGED = 1363ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff "android.net.nsd.STATE_CHANGED"; 1373ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 1383ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff /** 1393ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff * The lookup key for an int that indicates whether network service discovery is enabled 1403ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff * or disabled. Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}. 1413ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff * 1423ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff * @see #NSD_STATE_DISABLED 1433ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff * @see #NSD_STATE_ENABLED 1443ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff */ 1453ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff public static final String EXTRA_NSD_STATE = "nsd_state"; 1463ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 1473ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff /** 1483ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff * Network service discovery is disabled 1493ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff * 15054ac7a510245e5f00c16ff5595b6ae8d002c1c3bIrfan Sheriff * @see #ACTION_NSD_STATE_CHANGED 1513ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff */ 1523ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff public static final int NSD_STATE_DISABLED = 1; 1533ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 1543ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff /** 1553ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff * Network service discovery is enabled 1563ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff * 15754ac7a510245e5f00c16ff5595b6ae8d002c1c3bIrfan Sheriff * @see #ACTION_NSD_STATE_CHANGED 1583ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff */ 1593ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff public static final int NSD_STATE_ENABLED = 2; 1603ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 1617d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff private static final int BASE = Protocol.BASE_NSD_MANAGER; 1627d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 1637d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** @hide */ 1647d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff public static final int DISCOVER_SERVICES = BASE + 1; 1657d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** @hide */ 1667d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff public static final int DISCOVER_SERVICES_STARTED = BASE + 2; 1677d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** @hide */ 1687d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff public static final int DISCOVER_SERVICES_FAILED = BASE + 3; 1697d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** @hide */ 1707d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff public static final int SERVICE_FOUND = BASE + 4; 1717d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** @hide */ 1727d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff public static final int SERVICE_LOST = BASE + 5; 1737d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 1747d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** @hide */ 1757d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff public static final int STOP_DISCOVERY = BASE + 6; 1767d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** @hide */ 1777d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff public static final int STOP_DISCOVERY_FAILED = BASE + 7; 1787d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** @hide */ 1797d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff public static final int STOP_DISCOVERY_SUCCEEDED = BASE + 8; 1807d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 1817d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** @hide */ 1827d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff public static final int REGISTER_SERVICE = BASE + 9; 1837d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** @hide */ 1847d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff public static final int REGISTER_SERVICE_FAILED = BASE + 10; 1857d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** @hide */ 1867d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff public static final int REGISTER_SERVICE_SUCCEEDED = BASE + 11; 1877d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 1887d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** @hide */ 18992784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff public static final int UNREGISTER_SERVICE = BASE + 12; 1907d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** @hide */ 19192784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff public static final int UNREGISTER_SERVICE_FAILED = BASE + 13; 1927d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** @hide */ 19392784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff public static final int UNREGISTER_SERVICE_SUCCEEDED = BASE + 14; 1947d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 1957d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** @hide */ 19692784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff public static final int RESOLVE_SERVICE = BASE + 18; 197817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff /** @hide */ 19892784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff public static final int RESOLVE_SERVICE_FAILED = BASE + 19; 199817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff /** @hide */ 20092784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff public static final int RESOLVE_SERVICE_SUCCEEDED = BASE + 20; 201817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff 20292784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff /** @hide */ 2033ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff public static final int ENABLE = BASE + 24; 2043ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff /** @hide */ 2053ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff public static final int DISABLE = BASE + 25; 2063ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 20722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff /** @hide */ 20822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public static final int NATIVE_DAEMON_EVENT = BASE + 26; 20922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 21022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff /** Dns based service discovery protocol */ 21122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public static final int PROTOCOL_DNS_SD = 0x0001; 21222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 21322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private Context mContext; 21422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 21522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private static final int INVALID_LISTENER_KEY = 0; 21622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private int mListenerKey = 1; 21722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private final SparseArray mListenerMap = new SparseArray(); 21822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private final SparseArray<NsdServiceInfo> mServiceMap = new SparseArray<NsdServiceInfo>(); 21922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private final Object mMapLock = new Object(); 22022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 22122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private final AsyncChannel mAsyncChannel = new AsyncChannel(); 22222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private ServiceHandler mHandler; 22322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private final CountDownLatch mConnected = new CountDownLatch(1); 2243ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 2257d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** 2267d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * Create a new Nsd instance. Applications use 2277d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve 2287d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * {@link android.content.Context#NSD_SERVICE Context.NSD_SERVICE}. 2297d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * @param service the Binder interface 2307d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * @hide - hide this because it takes in a parameter of type INsdManager, which 2317d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * is a system private class. 2327d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff */ 23322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public NsdManager(Context context, INsdManager service) { 2347d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff mService = service; 23522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff mContext = context; 23622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff init(); 2377d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 2387d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 2397d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** 24022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * Failures are passed with {@link RegistrationListener#onRegistrationFailed}, 24122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * {@link RegistrationListener#onUnregistrationFailed}, 24222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * {@link DiscoveryListener#onStartDiscoveryFailed}, 24322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * {@link DiscoveryListener#onStopDiscoveryFailed} or {@link ResolveListener#onResolveFailed}. 24422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * 2457d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * Indicates that the operation failed due to an internal error. 2467d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff */ 24722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public static final int FAILURE_INTERNAL_ERROR = 0; 2487d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 2497d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** 250817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff * Indicates that the operation failed because it is already active. 251817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff */ 25222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public static final int FAILURE_ALREADY_ACTIVE = 3; 253817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff 254817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff /** 25522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * Indicates that the operation failed because the maximum outstanding 25622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * requests from the applications have reached. 257817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff */ 25822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public static final int FAILURE_MAX_LIMIT = 4; 2597d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 26022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff /** Interface for callback invocation for service discovery */ 26122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public interface DiscoveryListener { 2627d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 26322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public void onStartDiscoveryFailed(String serviceType, int errorCode); 2647d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 26522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public void onStopDiscoveryFailed(String serviceType, int errorCode); 2667d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 26722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public void onDiscoveryStarted(String serviceType); 2687d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 26922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public void onDiscoveryStopped(String serviceType); 2707d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 27122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public void onServiceFound(NsdServiceInfo serviceInfo); 2727d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 27322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public void onServiceLost(NsdServiceInfo serviceInfo); 2747d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 2757d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 2767d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 27792784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff /** Interface for callback invocation for service registration */ 27822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public interface RegistrationListener { 2797d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 28022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode); 2817d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 28222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode); 2837d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 28422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public void onServiceRegistered(NsdServiceInfo serviceInfo); 2857d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 28622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public void onServiceUnregistered(NsdServiceInfo serviceInfo); 2877d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 2887d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 28992784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff /** Interface for callback invocation for service resolution */ 29022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public interface ResolveListener { 2917d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 29222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode); 2937d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 29422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public void onServiceResolved(NsdServiceInfo serviceInfo); 2957d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 2967d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 29722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private class ServiceHandler extends Handler { 29822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff ServiceHandler(Looper looper) { 29922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff super(looper); 3007d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 3017d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 30222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff @Override 30322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public void handleMessage(Message message) { 30422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff switch (message.what) { 30522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 30622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); 3073fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt return; 30822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED: 309af2eefb70146a94dc4ae1d85ffe2b0e5e8f35a69Robert Greenwalt mConnected.countDown(); 3103fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt return; 31122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 31222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff Log.e(TAG, "Channel lost"); 3133fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt return; 3143fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt default: 31522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff break; 3163fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt } 3173fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt Object listener = getListener(message.arg2); 3183fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt if (listener == null) { 3193fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt Log.d(TAG, "Stale key " + message.arg2); 3203fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt return; 3213fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt } 3223fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt boolean listenerRemove = true; 3233fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt NsdServiceInfo ns = getNsdService(message.arg2); 3243fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt switch (message.what) { 32522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff case DISCOVER_SERVICES_STARTED: 3263fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt String s = getNsdServiceInfoType((NsdServiceInfo) message.obj); 32722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff ((DiscoveryListener) listener).onDiscoveryStarted(s); 32822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff // Keep listener until stop discovery 32922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff listenerRemove = false; 33022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff break; 33122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff case DISCOVER_SERVICES_FAILED: 3323fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt ((DiscoveryListener) listener).onStartDiscoveryFailed(getNsdServiceInfoType(ns), 3333fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt message.arg1); 33422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff break; 33522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff case SERVICE_FOUND: 33622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff ((DiscoveryListener) listener).onServiceFound((NsdServiceInfo) message.obj); 33722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff // Keep listener until stop discovery 33822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff listenerRemove = false; 33922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff break; 34022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff case SERVICE_LOST: 34122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff ((DiscoveryListener) listener).onServiceLost((NsdServiceInfo) message.obj); 34222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff // Keep listener until stop discovery 34322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff listenerRemove = false; 34422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff break; 34522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff case STOP_DISCOVERY_FAILED: 3463fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt ((DiscoveryListener) listener).onStopDiscoveryFailed(getNsdServiceInfoType(ns), 3473fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt message.arg1); 34822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff break; 34922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff case STOP_DISCOVERY_SUCCEEDED: 3503fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt ((DiscoveryListener) listener).onDiscoveryStopped(getNsdServiceInfoType(ns)); 35122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff break; 35222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff case REGISTER_SERVICE_FAILED: 3533fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt ((RegistrationListener) listener).onRegistrationFailed(ns, message.arg1); 35422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff break; 35522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff case REGISTER_SERVICE_SUCCEEDED: 35622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff ((RegistrationListener) listener).onServiceRegistered( 35722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff (NsdServiceInfo) message.obj); 35822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff // Keep listener until unregister 35922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff listenerRemove = false; 36022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff break; 36122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff case UNREGISTER_SERVICE_FAILED: 3623fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt ((RegistrationListener) listener).onUnregistrationFailed(ns, message.arg1); 36322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff break; 36422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff case UNREGISTER_SERVICE_SUCCEEDED: 3653fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt ((RegistrationListener) listener).onServiceUnregistered(ns); 36622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff break; 36722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff case RESOLVE_SERVICE_FAILED: 3683fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt ((ResolveListener) listener).onResolveFailed(ns, message.arg1); 36922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff break; 37022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff case RESOLVE_SERVICE_SUCCEEDED: 37122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff ((ResolveListener) listener).onServiceResolved((NsdServiceInfo) message.obj); 37222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff break; 37322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff default: 37422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff Log.d(TAG, "Ignored " + message); 37522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff break; 37622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 37722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (listenerRemove) { 37822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff removeListener(message.arg2); 3797d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 3807d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 38122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 3827d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 38322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private int putListener(Object listener, NsdServiceInfo s) { 38422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (listener == null) return INVALID_LISTENER_KEY; 38522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff int key; 38622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff synchronized (mMapLock) { 38722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff do { 38822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff key = mListenerKey++; 38922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } while (key == INVALID_LISTENER_KEY); 39022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff mListenerMap.put(key, listener); 39122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff mServiceMap.put(key, s); 39222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 39322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff return key; 39492784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff } 39592784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff 39622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private Object getListener(int key) { 39722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (key == INVALID_LISTENER_KEY) return null; 39822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff synchronized (mMapLock) { 39922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff return mListenerMap.get(key); 40022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 40122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 40222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 40322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private NsdServiceInfo getNsdService(int key) { 40422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff synchronized (mMapLock) { 40522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff return mServiceMap.get(key); 40622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 40722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 40822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 40922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private void removeListener(int key) { 41022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (key == INVALID_LISTENER_KEY) return; 41122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff synchronized (mMapLock) { 41222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff mListenerMap.remove(key); 41322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff mServiceMap.remove(key); 41422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 41522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 4167d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 41722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private int getListenerKey(Object listener) { 41822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff synchronized (mMapLock) { 41922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff int valueIndex = mListenerMap.indexOfValue(listener); 42022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (valueIndex != -1) { 42122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff return mListenerMap.keyAt(valueIndex); 42222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 42322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 42422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff return INVALID_LISTENER_KEY; 4257d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 4267d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 42722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 4283fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt private String getNsdServiceInfoType(NsdServiceInfo s) { 4293fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt if (s == null) return "?"; 4303fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt return s.getServiceType(); 4313fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt } 4323fc376b7336cfbddbb10ce3f93a853a927f6513aDave Platt 4337d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** 43422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * Initialize AsyncChannel 4357d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff */ 43622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private void init() { 43722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff final Messenger messenger = getMessenger(); 43822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (messenger == null) throw new RuntimeException("Failed to initialize"); 43922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff HandlerThread t = new HandlerThread("NsdManager"); 44022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff t.start(); 44122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff mHandler = new ServiceHandler(t.getLooper()); 44222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff mAsyncChannel.connect(mContext, mHandler, messenger); 44322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff try { 44422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff mConnected.await(); 44522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } catch (InterruptedException e) { 44622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff Log.e(TAG, "interrupted wait at init"); 44722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 4487d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 4497d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 4507d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** 45192784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * Register a service to be discovered by other services. 45292784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * 45392784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * <p> The function call immediately returns after sending a request to register service 45492784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * to the framework. The application is notified of a success to initiate 45522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * discovery through the callback {@link RegistrationListener#onServiceRegistered} or a failure 45622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * through {@link RegistrationListener#onRegistrationFailed}. 45792784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * 45822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * @param serviceInfo The service being registered 45922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * @param protocolType The service discovery protocol 46022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * @param listener The listener notifies of a successful registration and is used to 46122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * unregister this service through a call on {@link #unregisterService}. Cannot be null. 4627d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff */ 46322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public void registerService(NsdServiceInfo serviceInfo, int protocolType, 46422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff RegistrationListener listener) { 46522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (TextUtils.isEmpty(serviceInfo.getServiceName()) || 46622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff TextUtils.isEmpty(serviceInfo.getServiceType())) { 46792784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff throw new IllegalArgumentException("Service name or type cannot be empty"); 46892784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff } 46922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (serviceInfo.getPort() <= 0) { 47092784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff throw new IllegalArgumentException("Invalid port number"); 47192784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff } 47222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (listener == null) { 47322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff throw new IllegalArgumentException("listener cannot be null"); 47422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 47522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (protocolType != PROTOCOL_DNS_SD) { 47622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff throw new IllegalArgumentException("Unsupported protocol"); 47722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 47822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff mAsyncChannel.sendMessage(REGISTER_SERVICE, 0, putListener(listener, serviceInfo), 47922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff serviceInfo); 4807d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 4817d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 482817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff /** 48322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * Unregister a service registered through {@link #registerService}. A successful 48422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * unregister is notified to the application with a call to 48522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * {@link RegistrationListener#onServiceUnregistered}. 48622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * 48722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * @param listener This should be the listener object that was passed to 48822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * {@link #registerService}. It identifies the service that should be unregistered 48922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * and notifies of a successful unregistration. 490817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff */ 49122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public void unregisterService(RegistrationListener listener) { 49222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff int id = getListenerKey(listener); 49322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (id == INVALID_LISTENER_KEY) { 49422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff throw new IllegalArgumentException("listener not registered"); 49522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 49622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (listener == null) { 49722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff throw new IllegalArgumentException("listener cannot be null"); 49822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 49922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff mAsyncChannel.sendMessage(UNREGISTER_SERVICE, 0, id); 5007d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 5017d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 50292784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff /** 50392784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * Initiate service discovery to browse for instances of a service type. Service discovery 50492784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * consumes network bandwidth and will continue until the application calls 50592784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * {@link #stopServiceDiscovery}. 50692784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * 50792784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * <p> The function call immediately returns after sending a request to start service 50892784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * discovery to the framework. The application is notified of a success to initiate 50922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * discovery through the callback {@link DiscoveryListener#onDiscoveryStarted} or a failure 51022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * through {@link DiscoveryListener#onStartDiscoveryFailed}. 51192784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * 51292784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * <p> Upon successful start, application is notified when a service is found with 51322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * {@link DiscoveryListener#onServiceFound} or when a service is lost with 51422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * {@link DiscoveryListener#onServiceLost}. 51592784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * 51692784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * <p> Upon failure to start, service discovery is not active and application does 51792784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * not need to invoke {@link #stopServiceDiscovery} 51892784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * 51992784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * @param serviceType The service type being discovered. Examples include "_http._tcp" for 52092784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * http services or "_ipp._tcp" for printers 52122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * @param protocolType The service discovery protocol 52222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * @param listener The listener notifies of a successful discovery and is used 52322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}. 52422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * Cannot be null. 52592784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff */ 52622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) { 52792784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff if (listener == null) { 52822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff throw new IllegalArgumentException("listener cannot be null"); 52992784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff } 53092784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff if (TextUtils.isEmpty(serviceType)) { 53122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff throw new IllegalArgumentException("Service type cannot be empty"); 53292784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff } 53322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 53422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (protocolType != PROTOCOL_DNS_SD) { 53522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff throw new IllegalArgumentException("Unsupported protocol"); 53622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 53722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 53822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff NsdServiceInfo s = new NsdServiceInfo(); 5397d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff s.setServiceType(serviceType); 54022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff mAsyncChannel.sendMessage(DISCOVER_SERVICES, 0, putListener(listener, s), s); 5417d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 5427d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 54392784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff /** 54492784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * Stop service discovery initiated with {@link #discoverServices}. An active service 54522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * discovery is notified to the application with {@link DiscoveryListener#onDiscoveryStarted} 54622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * and it stays active until the application invokes a stop service discovery. A successful 54722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * stop is notified to with a call to {@link DiscoveryListener#onDiscoveryStopped}. 54892784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * 54922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * <p> Upon failure to stop service discovery, application is notified through 55022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * {@link DiscoveryListener#onStopDiscoveryFailed}. 55192784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * 55222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * @param listener This should be the listener object that was passed to {@link #discoverServices}. 55322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * It identifies the discovery that should be stopped and notifies of a successful stop. 55492784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff */ 55522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public void stopServiceDiscovery(DiscoveryListener listener) { 55622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff int id = getListenerKey(listener); 55722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (id == INVALID_LISTENER_KEY) { 55822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff throw new IllegalArgumentException("service discovery not active on listener"); 55922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 56022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (listener == null) { 56122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff throw new IllegalArgumentException("listener cannot be null"); 56222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 56322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff mAsyncChannel.sendMessage(STOP_DISCOVERY, 0, id); 5647d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 5657d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 56692784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff /** 56792784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * Resolve a discovered service. An application can resolve a service right before 56892784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * establishing a connection to fetch the IP and port details on which to setup 56992784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * the connection. 57092784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * 57122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * @param serviceInfo service to be resolved 57292784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff * @param listener to receive callback upon success or failure. Cannot be null. 57392784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff */ 57422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff public void resolveService(NsdServiceInfo serviceInfo, ResolveListener listener) { 57522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (TextUtils.isEmpty(serviceInfo.getServiceName()) || 57622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff TextUtils.isEmpty(serviceInfo.getServiceType())) { 57792784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff throw new IllegalArgumentException("Service name or type cannot be empty"); 57892784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff } 57922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (listener == null) { 58022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff throw new IllegalArgumentException("listener cannot be null"); 58122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 58222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff mAsyncChannel.sendMessage(RESOLVE_SERVICE, 0, putListener(listener, serviceInfo), 58322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff serviceInfo); 584817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } 585817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff 5863ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff /** Internal use only @hide */ 5873ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff public void setEnabled(boolean enabled) { 5883ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff try { 5893ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff mService.setEnabled(enabled); 5903ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } catch (RemoteException e) { } 5913ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 5923ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 5937d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** 5947d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * Get a reference to NetworkService handler. This is used to establish 5957d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * an AsyncChannel communication with the service 5967d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * 5977d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * @return Messenger pointing to the NetworkService handler 5987d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff */ 5997d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff private Messenger getMessenger() { 6007d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff try { 6017d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff return mService.getMessenger(); 6027d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } catch (RemoteException e) { 6037d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff return null; 6047d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 6057d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 6067d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff} 607