blob: 93799550dcd7e689f7b9554a3422186a9c185e6a [file] [log] [blame]
Irfan Sheriff7d024d32012-03-22 17:01:39 -07001/*
2 * Copyright (C) 2010 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 com.android.server;
18
19import android.content.Context;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -070020import android.content.ContentResolver;
21import android.content.Intent;
Irfan Sheriff7d024d32012-03-22 17:01:39 -070022import android.content.pm.PackageManager;
Irfan Sheriff919aca52012-06-01 16:44:13 -070023import android.database.ContentObserver;
Irfan Sheriff22af38c2012-05-03 16:44:27 -070024import android.net.nsd.NsdServiceInfo;
Irfan Sheriff7d024d32012-03-22 17:01:39 -070025import android.net.nsd.DnsSdTxtRecord;
26import android.net.nsd.INsdManager;
27import android.net.nsd.NsdManager;
28import android.os.Binder;
29import android.os.Handler;
30import android.os.HandlerThread;
31import android.os.Message;
32import android.os.Messenger;
33import android.os.IBinder;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070034import android.os.UserHandle;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -070035import android.provider.Settings;
Irfan Sheriff7d024d32012-03-22 17:01:39 -070036import android.util.Slog;
Irfan Sheriff22af38c2012-05-03 16:44:27 -070037import android.util.SparseArray;
Irfan Sheriff7d024d32012-03-22 17:01:39 -070038
39import java.io.FileDescriptor;
40import java.io.PrintWriter;
Irfan Sheriff817388e2012-04-11 14:52:19 -070041import java.net.InetAddress;
Irfan Sheriff7d024d32012-03-22 17:01:39 -070042import java.util.ArrayList;
Irfan Sheriff817388e2012-04-11 14:52:19 -070043import java.util.HashMap;
Irfan Sheriff7d024d32012-03-22 17:01:39 -070044import java.util.List;
Irfan Sheriff817388e2012-04-11 14:52:19 -070045import java.util.concurrent.CountDownLatch;
Irfan Sheriff7d024d32012-03-22 17:01:39 -070046
47import com.android.internal.app.IBatteryStats;
48import com.android.internal.telephony.TelephonyIntents;
49import com.android.internal.util.AsyncChannel;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -070050import com.android.internal.util.Protocol;
51import com.android.internal.util.State;
52import com.android.internal.util.StateMachine;
Irfan Sheriff7d024d32012-03-22 17:01:39 -070053import com.android.server.am.BatteryStatsService;
54import com.android.server.NativeDaemonConnector.Command;
55import com.android.internal.R;
56
57/**
58 * Network Service Discovery Service handles remote service discovery operation requests by
59 * implementing the INsdManager interface.
60 *
61 * @hide
62 */
63public class NsdService extends INsdManager.Stub {
64 private static final String TAG = "NsdService";
65 private static final String MDNS_TAG = "mDnsConnector";
66
67 private static final boolean DBG = true;
68
69 private Context mContext;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -070070 private ContentResolver mContentResolver;
71 private NsdStateMachine mNsdStateMachine;
Irfan Sheriff7d024d32012-03-22 17:01:39 -070072
73 /**
74 * Clients receiving asynchronous messages
75 */
Irfan Sheriff817388e2012-04-11 14:52:19 -070076 private HashMap<Messenger, ClientInfo> mClients = new HashMap<Messenger, ClientInfo>();
Irfan Sheriff7d024d32012-03-22 17:01:39 -070077
Irfan Sheriff22af38c2012-05-03 16:44:27 -070078 /* A map from unique id to client info */
79 private SparseArray<ClientInfo> mIdToClientInfoMap= new SparseArray<ClientInfo>();
80
Irfan Sheriff7d024d32012-03-22 17:01:39 -070081 private AsyncChannel mReplyChannel = new AsyncChannel();
82
Irfan Sheriff817388e2012-04-11 14:52:19 -070083 private int INVALID_ID = 0;
84 private int mUniqueId = 1;
85
Irfan Sheriff3ef889b2012-04-17 23:15:29 -070086 private static final int BASE = Protocol.BASE_NSD_MANAGER;
Irfan Sheriff22af38c2012-05-03 16:44:27 -070087 private static final int CMD_TO_STRING_COUNT = NsdManager.RESOLVE_SERVICE - BASE + 1;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -070088 private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT];
Irfan Sheriff7d024d32012-03-22 17:01:39 -070089
Irfan Sheriff3ef889b2012-04-17 23:15:29 -070090 static {
91 sCmdToString[NsdManager.DISCOVER_SERVICES - BASE] = "DISCOVER";
92 sCmdToString[NsdManager.STOP_DISCOVERY - BASE] = "STOP-DISCOVER";
93 sCmdToString[NsdManager.REGISTER_SERVICE - BASE] = "REGISTER";
94 sCmdToString[NsdManager.UNREGISTER_SERVICE - BASE] = "UNREGISTER";
95 sCmdToString[NsdManager.RESOLVE_SERVICE - BASE] = "RESOLVE";
Irfan Sheriff3ef889b2012-04-17 23:15:29 -070096 }
Irfan Sheriff7d024d32012-03-22 17:01:39 -070097
Irfan Sheriff3ef889b2012-04-17 23:15:29 -070098 private static String cmdToString(int cmd) {
99 cmd -= BASE;
100 if ((cmd >= 0) && (cmd < sCmdToString.length)) {
101 return sCmdToString[cmd];
102 } else {
103 return null;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700104 }
105 }
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700106
107 private class NsdStateMachine extends StateMachine {
108
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700109 private final DefaultState mDefaultState = new DefaultState();
110 private final DisabledState mDisabledState = new DisabledState();
111 private final EnabledState mEnabledState = new EnabledState();
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700112
113 @Override
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700114 protected String getWhatToString(int what) {
115 return cmdToString(what);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700116 }
117
Irfan Sheriff919aca52012-06-01 16:44:13 -0700118 /**
119 * Observes the NSD on/off setting, and takes action when changed.
120 */
121 private void registerForNsdSetting() {
122 ContentObserver contentObserver = new ContentObserver(this.getHandler()) {
123 @Override
124 public void onChange(boolean selfChange) {
125 if (isNsdEnabled()) {
126 mNsdStateMachine.sendMessage(NsdManager.ENABLE);
127 } else {
128 mNsdStateMachine.sendMessage(NsdManager.DISABLE);
129 }
130 }
131 };
132
133 mContext.getContentResolver().registerContentObserver(
Jeff Sharkey625239a2012-09-26 22:03:49 -0700134 Settings.Global.getUriFor(Settings.Global.NSD_ON),
Irfan Sheriff919aca52012-06-01 16:44:13 -0700135 false, contentObserver);
136 }
137
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700138 NsdStateMachine(String name) {
139 super(name);
140 addState(mDefaultState);
141 addState(mDisabledState, mDefaultState);
142 addState(mEnabledState, mDefaultState);
143 if (isNsdEnabled()) {
144 setInitialState(mEnabledState);
145 } else {
146 setInitialState(mDisabledState);
147 }
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700148 setLogRecSize(25);
Irfan Sheriff919aca52012-06-01 16:44:13 -0700149 registerForNsdSetting();
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700150 }
151
152 class DefaultState extends State {
153 @Override
154 public boolean processMessage(Message msg) {
Dave Plattf31760c2014-03-07 14:48:22 -0800155 ClientInfo cInfo = null;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700156 switch (msg.what) {
157 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
158 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
159 AsyncChannel c = (AsyncChannel) msg.obj;
160 if (DBG) Slog.d(TAG, "New client listening to asynchronous messages");
161 c.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED);
Dave Plattf31760c2014-03-07 14:48:22 -0800162 cInfo = new ClientInfo(c, msg.replyTo);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700163 mClients.put(msg.replyTo, cInfo);
164 } else {
165 Slog.e(TAG, "Client connection failure, error=" + msg.arg1);
166 }
167 break;
168 case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
Dave Plattf31760c2014-03-07 14:48:22 -0800169 switch (msg.arg1) {
170 case AsyncChannel.STATUS_SEND_UNSUCCESSFUL:
171 Slog.e(TAG, "Send failed, client connection lost");
172 break;
173 case AsyncChannel.STATUS_REMOTE_DISCONNECTION:
174 if (DBG) Slog.d(TAG, "Client disconnected");
175 break;
176 default:
177 if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1);
178 break;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700179 }
Dave Plattf31760c2014-03-07 14:48:22 -0800180 cInfo = mClients.get(msg.replyTo);
181 if (cInfo != null) {
182 cInfo.expungeAllRequests();
183 mClients.remove(msg.replyTo);
184 }
185 //Last client
186 if (mClients.size() == 0) {
187 stopMDnsDaemon();
188 }
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700189 break;
190 case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
191 AsyncChannel ac = new AsyncChannel();
192 ac.connect(mContext, getHandler(), msg.replyTo);
193 break;
194 case NsdManager.DISCOVER_SERVICES:
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700195 replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED,
196 NsdManager.FAILURE_INTERNAL_ERROR);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700197 break;
198 case NsdManager.STOP_DISCOVERY:
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700199 replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED,
200 NsdManager.FAILURE_INTERNAL_ERROR);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700201 break;
202 case NsdManager.REGISTER_SERVICE:
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700203 replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED,
204 NsdManager.FAILURE_INTERNAL_ERROR);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700205 break;
206 case NsdManager.UNREGISTER_SERVICE:
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700207 replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED,
208 NsdManager.FAILURE_INTERNAL_ERROR);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700209 break;
210 case NsdManager.RESOLVE_SERVICE:
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700211 replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED,
212 NsdManager.FAILURE_INTERNAL_ERROR);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700213 break;
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700214 case NsdManager.NATIVE_DAEMON_EVENT:
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700215 default:
216 Slog.e(TAG, "Unhandled " + msg);
217 return NOT_HANDLED;
218 }
219 return HANDLED;
220 }
221 }
222
223 class DisabledState extends State {
224 @Override
225 public void enter() {
226 sendNsdStateChangeBroadcast(false);
227 }
228
229 @Override
230 public boolean processMessage(Message msg) {
231 switch (msg.what) {
232 case NsdManager.ENABLE:
233 transitionTo(mEnabledState);
234 break;
235 default:
236 return NOT_HANDLED;
237 }
238 return HANDLED;
239 }
240 }
241
242 class EnabledState extends State {
243 @Override
244 public void enter() {
245 sendNsdStateChangeBroadcast(true);
246 if (mClients.size() > 0) {
247 startMDnsDaemon();
248 }
249 }
250
251 @Override
252 public void exit() {
253 if (mClients.size() > 0) {
254 stopMDnsDaemon();
255 }
256 }
257
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700258 private boolean requestLimitReached(ClientInfo clientInfo) {
259 if (clientInfo.mClientIds.size() >= ClientInfo.MAX_LIMIT) {
260 if (DBG) Slog.d(TAG, "Exceeded max outstanding requests " + clientInfo);
261 return true;
262 }
263 return false;
264 }
265
Dave Plattf31760c2014-03-07 14:48:22 -0800266 private void storeRequestMap(int clientId, int globalId, ClientInfo clientInfo, int what) {
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700267 clientInfo.mClientIds.put(clientId, globalId);
Dave Plattf31760c2014-03-07 14:48:22 -0800268 clientInfo.mClientRequests.put(clientId, what);
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700269 mIdToClientInfoMap.put(globalId, clientInfo);
270 }
271
272 private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) {
273 clientInfo.mClientIds.remove(clientId);
Dave Plattf31760c2014-03-07 14:48:22 -0800274 clientInfo.mClientRequests.remove(clientId);
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700275 mIdToClientInfoMap.remove(globalId);
276 }
277
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700278 @Override
279 public boolean processMessage(Message msg) {
280 ClientInfo clientInfo;
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700281 NsdServiceInfo servInfo;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700282 boolean result = HANDLED;
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700283 int id;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700284 switch (msg.what) {
285 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
286 //First client
287 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL &&
288 mClients.size() == 0) {
289 startMDnsDaemon();
290 }
291 result = NOT_HANDLED;
292 break;
293 case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700294 result = NOT_HANDLED;
295 break;
296 case NsdManager.DISABLE:
297 //TODO: cleanup clients
298 transitionTo(mDisabledState);
299 break;
300 case NsdManager.DISCOVER_SERVICES:
301 if (DBG) Slog.d(TAG, "Discover services");
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700302 servInfo = (NsdServiceInfo) msg.obj;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700303 clientInfo = mClients.get(msg.replyTo);
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700304
305 if (requestLimitReached(clientInfo)) {
306 replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED,
307 NsdManager.FAILURE_MAX_LIMIT);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700308 break;
309 }
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700310
311 id = getUniqueId();
312 if (discoverServices(id, servInfo.getServiceType())) {
313 if (DBG) {
314 Slog.d(TAG, "Discover " + msg.arg2 + " " + id +
315 servInfo.getServiceType());
316 }
Dave Plattf31760c2014-03-07 14:48:22 -0800317 storeRequestMap(msg.arg2, id, clientInfo, msg.what);
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700318 replyToMessage(msg, NsdManager.DISCOVER_SERVICES_STARTED, servInfo);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700319 } else {
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700320 stopServiceDiscovery(id);
321 replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED,
322 NsdManager.FAILURE_INTERNAL_ERROR);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700323 }
324 break;
325 case NsdManager.STOP_DISCOVERY:
326 if (DBG) Slog.d(TAG, "Stop service discovery");
327 clientInfo = mClients.get(msg.replyTo);
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700328
329 try {
330 id = clientInfo.mClientIds.get(msg.arg2).intValue();
331 } catch (NullPointerException e) {
332 replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED,
333 NsdManager.FAILURE_INTERNAL_ERROR);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700334 break;
335 }
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700336 removeRequestMap(msg.arg2, id, clientInfo);
337 if (stopServiceDiscovery(id)) {
338 replyToMessage(msg, NsdManager.STOP_DISCOVERY_SUCCEEDED);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700339 } else {
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700340 replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED,
341 NsdManager.FAILURE_INTERNAL_ERROR);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700342 }
343 break;
344 case NsdManager.REGISTER_SERVICE:
345 if (DBG) Slog.d(TAG, "Register service");
346 clientInfo = mClients.get(msg.replyTo);
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700347 if (requestLimitReached(clientInfo)) {
348 replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED,
349 NsdManager.FAILURE_MAX_LIMIT);
350 break;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700351 }
352
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700353 id = getUniqueId();
354 if (registerService(id, (NsdServiceInfo) msg.obj)) {
355 if (DBG) Slog.d(TAG, "Register " + msg.arg2 + " " + id);
Dave Plattf31760c2014-03-07 14:48:22 -0800356 storeRequestMap(msg.arg2, id, clientInfo, msg.what);
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700357 // Return success after mDns reports success
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700358 } else {
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700359 unregisterService(id);
360 replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED,
361 NsdManager.FAILURE_INTERNAL_ERROR);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700362 }
363 break;
364 case NsdManager.UNREGISTER_SERVICE:
365 if (DBG) Slog.d(TAG, "unregister service");
366 clientInfo = mClients.get(msg.replyTo);
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700367 try {
368 id = clientInfo.mClientIds.get(msg.arg2).intValue();
369 } catch (NullPointerException e) {
370 replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED,
371 NsdManager.FAILURE_INTERNAL_ERROR);
372 break;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700373 }
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700374 removeRequestMap(msg.arg2, id, clientInfo);
375 if (unregisterService(id)) {
376 replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_SUCCEEDED);
377 } else {
378 replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED,
379 NsdManager.FAILURE_INTERNAL_ERROR);
380 }
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700381 break;
382 case NsdManager.RESOLVE_SERVICE:
383 if (DBG) Slog.d(TAG, "Resolve service");
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700384 servInfo = (NsdServiceInfo) msg.obj;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700385 clientInfo = mClients.get(msg.replyTo);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700386
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700387
388 if (clientInfo.mResolvedService != null) {
389 replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED,
390 NsdManager.FAILURE_ALREADY_ACTIVE);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700391 break;
392 }
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700393
394 id = getUniqueId();
395 if (resolveService(id, servInfo)) {
396 clientInfo.mResolvedService = new NsdServiceInfo();
Dave Plattf31760c2014-03-07 14:48:22 -0800397 storeRequestMap(msg.arg2, id, clientInfo, msg.what);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700398 } else {
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700399 replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED,
400 NsdManager.FAILURE_INTERNAL_ERROR);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700401 }
402 break;
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700403 case NsdManager.NATIVE_DAEMON_EVENT:
404 NativeEvent event = (NativeEvent) msg.obj;
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700405 if (!handleNativeEvent(event.code, event.raw,
406 NativeDaemonEvent.unescapeArgs(event.raw))) {
407 result = NOT_HANDLED;
408 }
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700409 break;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700410 default:
411 result = NOT_HANDLED;
412 break;
413 }
414 return result;
415 }
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700416
417 private boolean handleNativeEvent(int code, String raw, String[] cooked) {
418 boolean handled = true;
419 NsdServiceInfo servInfo;
420 int id = Integer.parseInt(cooked[1]);
421 ClientInfo clientInfo = mIdToClientInfoMap.get(id);
422 if (clientInfo == null) {
423 Slog.e(TAG, "Unique id with no client mapping: " + id);
424 handled = false;
425 return handled;
426 }
427
428 /* This goes in response as msg.arg2 */
429 int clientId = -1;
430 int keyId = clientInfo.mClientIds.indexOfValue(id);
431 if (keyId != -1) {
432 clientId = clientInfo.mClientIds.keyAt(keyId);
Vinit Deshapnde8ed09e82013-06-25 19:45:03 -0700433 } else {
434 // This can happen because of race conditions. For example,
435 // SERVICE_FOUND may race with STOP_SERVICE_DISCOVERY,
436 // and we may get in this situation.
437 Slog.d(TAG, "Notification for a listener that is no longer active: " + id);
438 handled = false;
439 return handled;
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700440 }
Vinit Deshapnde8ed09e82013-06-25 19:45:03 -0700441
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700442 switch (code) {
443 case NativeResponseCode.SERVICE_FOUND:
444 /* NNN uniqueId serviceName regType domain */
445 if (DBG) Slog.d(TAG, "SERVICE_FOUND Raw: " + raw);
446 servInfo = new NsdServiceInfo(cooked[2], cooked[3], null);
447 clientInfo.mChannel.sendMessage(NsdManager.SERVICE_FOUND, 0,
448 clientId, servInfo);
449 break;
450 case NativeResponseCode.SERVICE_LOST:
451 /* NNN uniqueId serviceName regType domain */
452 if (DBG) Slog.d(TAG, "SERVICE_LOST Raw: " + raw);
453 servInfo = new NsdServiceInfo(cooked[2], cooked[3], null);
454 clientInfo.mChannel.sendMessage(NsdManager.SERVICE_LOST, 0,
455 clientId, servInfo);
456 break;
457 case NativeResponseCode.SERVICE_DISCOVERY_FAILED:
458 /* NNN uniqueId errorCode */
459 if (DBG) Slog.d(TAG, "SERVICE_DISC_FAILED Raw: " + raw);
460 clientInfo.mChannel.sendMessage(NsdManager.DISCOVER_SERVICES_FAILED,
461 NsdManager.FAILURE_INTERNAL_ERROR, clientId);
462 break;
463 case NativeResponseCode.SERVICE_REGISTERED:
464 /* NNN regId serviceName regType */
465 if (DBG) Slog.d(TAG, "SERVICE_REGISTERED Raw: " + raw);
466 servInfo = new NsdServiceInfo(cooked[2], null, null);
467 clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_SUCCEEDED,
468 id, clientId, servInfo);
469 break;
470 case NativeResponseCode.SERVICE_REGISTRATION_FAILED:
471 /* NNN regId errorCode */
472 if (DBG) Slog.d(TAG, "SERVICE_REGISTER_FAILED Raw: " + raw);
473 clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_FAILED,
474 NsdManager.FAILURE_INTERNAL_ERROR, clientId);
475 break;
476 case NativeResponseCode.SERVICE_UPDATED:
477 /* NNN regId */
478 break;
479 case NativeResponseCode.SERVICE_UPDATE_FAILED:
480 /* NNN regId errorCode */
481 break;
482 case NativeResponseCode.SERVICE_RESOLVED:
483 /* NNN resolveId fullName hostName port txtlen txtdata */
484 if (DBG) Slog.d(TAG, "SERVICE_RESOLVED Raw: " + raw);
485 int index = cooked[2].indexOf(".");
486 if (index == -1) {
487 Slog.e(TAG, "Invalid service found " + raw);
488 break;
489 }
490 String name = cooked[2].substring(0, index);
491 String rest = cooked[2].substring(index);
492 String type = rest.replace(".local.", "");
493
494 clientInfo.mResolvedService.setServiceName(name);
495 clientInfo.mResolvedService.setServiceType(type);
496 clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4]));
497
498 stopResolveService(id);
Vinit Deshapnde40387242013-11-12 15:36:37 -0800499 removeRequestMap(clientId, id, clientInfo);
500
501 int id2 = getUniqueId();
502 if (getAddrInfo(id2, cooked[3])) {
Dave Plattf31760c2014-03-07 14:48:22 -0800503 storeRequestMap(clientId, id2, clientInfo, NsdManager.RESOLVE_SERVICE);
Vinit Deshapnde40387242013-11-12 15:36:37 -0800504 } else {
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700505 clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED,
506 NsdManager.FAILURE_INTERNAL_ERROR, clientId);
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700507 clientInfo.mResolvedService = null;
508 }
509 break;
510 case NativeResponseCode.SERVICE_RESOLUTION_FAILED:
511 /* NNN resolveId errorCode */
512 if (DBG) Slog.d(TAG, "SERVICE_RESOLVE_FAILED Raw: " + raw);
513 stopResolveService(id);
514 removeRequestMap(clientId, id, clientInfo);
515 clientInfo.mResolvedService = null;
516 clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED,
517 NsdManager.FAILURE_INTERNAL_ERROR, clientId);
518 break;
519 case NativeResponseCode.SERVICE_GET_ADDR_FAILED:
520 /* NNN resolveId errorCode */
521 stopGetAddrInfo(id);
522 removeRequestMap(clientId, id, clientInfo);
523 clientInfo.mResolvedService = null;
524 if (DBG) Slog.d(TAG, "SERVICE_RESOLVE_FAILED Raw: " + raw);
525 clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED,
526 NsdManager.FAILURE_INTERNAL_ERROR, clientId);
527 break;
528 case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS:
529 /* NNN resolveId hostname ttl addr */
530 if (DBG) Slog.d(TAG, "SERVICE_GET_ADDR_SUCCESS Raw: " + raw);
531 try {
532 clientInfo.mResolvedService.setHost(InetAddress.getByName(cooked[4]));
533 clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_SUCCEEDED,
534 0, clientId, clientInfo.mResolvedService);
535 } catch (java.net.UnknownHostException e) {
536 clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED,
537 NsdManager.FAILURE_INTERNAL_ERROR, clientId);
538 }
539 stopGetAddrInfo(id);
540 removeRequestMap(clientId, id, clientInfo);
541 clientInfo.mResolvedService = null;
542 break;
543 default:
544 handled = false;
545 break;
546 }
547 return handled;
548 }
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700549 }
550 }
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700551
552 private NativeDaemonConnector mNativeConnector;
553 private final CountDownLatch mNativeDaemonConnected = new CountDownLatch(1);
554
555 private NsdService(Context context) {
556 mContext = context;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700557 mContentResolver = context.getContentResolver();
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700558
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700559 mNativeConnector = new NativeDaemonConnector(new NativeCallbackReceiver(), "mdns", 10,
560 MDNS_TAG, 25);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700561
562 mNsdStateMachine = new NsdStateMachine(TAG);
563 mNsdStateMachine.start();
564
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700565 Thread th = new Thread(mNativeConnector, MDNS_TAG);
566 th.start();
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700567 }
568
569 public static NsdService create(Context context) throws InterruptedException {
570 NsdService service = new NsdService(context);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700571 service.mNativeDaemonConnected.await();
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700572 return service;
573 }
574
575 public Messenger getMessenger() {
Irfan Sheriff92784672012-04-13 12:15:41 -0700576 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET,
577 "NsdService");
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700578 return new Messenger(mNsdStateMachine.getHandler());
579 }
580
581 public void setEnabled(boolean enable) {
582 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL,
583 "NsdService");
Jeff Sharkey625239a2012-09-26 22:03:49 -0700584 Settings.Global.putInt(mContentResolver, Settings.Global.NSD_ON, enable ? 1 : 0);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700585 if (enable) {
586 mNsdStateMachine.sendMessage(NsdManager.ENABLE);
587 } else {
588 mNsdStateMachine.sendMessage(NsdManager.DISABLE);
589 }
590 }
591
592 private void sendNsdStateChangeBroadcast(boolean enabled) {
Irfan Sheriff54ac7a52012-04-19 10:26:34 -0700593 final Intent intent = new Intent(NsdManager.ACTION_NSD_STATE_CHANGED);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700594 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
595 if (enabled) {
596 intent.putExtra(NsdManager.EXTRA_NSD_STATE, NsdManager.NSD_STATE_ENABLED);
597 } else {
598 intent.putExtra(NsdManager.EXTRA_NSD_STATE, NsdManager.NSD_STATE_DISABLED);
599 }
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700600 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700601 }
602
603 private boolean isNsdEnabled() {
Jeff Sharkey625239a2012-09-26 22:03:49 -0700604 boolean ret = Settings.Global.getInt(mContentResolver, Settings.Global.NSD_ON, 1) == 1;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700605 if (DBG) Slog.d(TAG, "Network service discovery enabled " + ret);
606 return ret;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700607 }
608
Irfan Sheriff817388e2012-04-11 14:52:19 -0700609 private int getUniqueId() {
610 if (++mUniqueId == INVALID_ID) return ++mUniqueId;
611 return mUniqueId;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700612 }
613
Irfan Sheriff817388e2012-04-11 14:52:19 -0700614 /* These should be in sync with system/netd/mDnsResponseCode.h */
615 class NativeResponseCode {
616 public static final int SERVICE_DISCOVERY_FAILED = 602;
617 public static final int SERVICE_FOUND = 603;
618 public static final int SERVICE_LOST = 604;
619
620 public static final int SERVICE_REGISTRATION_FAILED = 605;
621 public static final int SERVICE_REGISTERED = 606;
622
623 public static final int SERVICE_RESOLUTION_FAILED = 607;
624 public static final int SERVICE_RESOLVED = 608;
625
626 public static final int SERVICE_UPDATED = 609;
627 public static final int SERVICE_UPDATE_FAILED = 610;
628
629 public static final int SERVICE_GET_ADDR_FAILED = 611;
630 public static final int SERVICE_GET_ADDR_SUCCESS = 612;
631 }
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700632
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700633 private class NativeEvent {
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700634 final int code;
635 final String raw;
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700636
637 NativeEvent(int code, String raw) {
638 this.code = code;
639 this.raw = raw;
640 }
641 }
642
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700643 class NativeCallbackReceiver implements INativeDaemonConnectorCallbacks {
644 public void onDaemonConnected() {
645 mNativeDaemonConnected.countDown();
646 }
647
648 public boolean onEvent(int code, String raw, String[] cooked) {
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700649 // TODO: NDC translates a message to a callback, we could enhance NDC to
650 // directly interact with a state machine through messages
651 NativeEvent event = new NativeEvent(code, raw);
652 mNsdStateMachine.sendMessage(NsdManager.NATIVE_DAEMON_EVENT, event);
653 return true;
654 }
655 }
Irfan Sheriff817388e2012-04-11 14:52:19 -0700656
Irfan Sheriff817388e2012-04-11 14:52:19 -0700657 private boolean startMDnsDaemon() {
658 if (DBG) Slog.d(TAG, "startMDnsDaemon");
659 try {
660 mNativeConnector.execute("mdnssd", "start-service");
661 } catch(NativeDaemonConnectorException e) {
662 Slog.e(TAG, "Failed to start daemon" + e);
663 return false;
664 }
665 return true;
666 }
667
668 private boolean stopMDnsDaemon() {
669 if (DBG) Slog.d(TAG, "stopMDnsDaemon");
670 try {
671 mNativeConnector.execute("mdnssd", "stop-service");
672 } catch(NativeDaemonConnectorException e) {
673 Slog.e(TAG, "Failed to start daemon" + e);
674 return false;
675 }
676 return true;
677 }
678
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700679 private boolean registerService(int regId, NsdServiceInfo service) {
Irfan Sheriff817388e2012-04-11 14:52:19 -0700680 if (DBG) Slog.d(TAG, "registerService: " + regId + " " + service);
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700681 try {
682 //Add txtlen and txtdata
683 mNativeConnector.execute("mdnssd", "register", regId, service.getServiceName(),
684 service.getServiceType(), service.getPort());
685 } catch(NativeDaemonConnectorException e) {
Irfan Sheriff817388e2012-04-11 14:52:19 -0700686 Slog.e(TAG, "Failed to execute registerService " + e);
687 return false;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700688 }
Irfan Sheriff817388e2012-04-11 14:52:19 -0700689 return true;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700690 }
691
Irfan Sheriff817388e2012-04-11 14:52:19 -0700692 private boolean unregisterService(int regId) {
693 if (DBG) Slog.d(TAG, "unregisterService: " + regId);
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700694 try {
Irfan Sheriff817388e2012-04-11 14:52:19 -0700695 mNativeConnector.execute("mdnssd", "stop-register", regId);
696 } catch(NativeDaemonConnectorException e) {
697 Slog.e(TAG, "Failed to execute unregisterService " + e);
698 return false;
699 }
700 return true;
701 }
702
703 private boolean updateService(int regId, DnsSdTxtRecord t) {
704 if (DBG) Slog.d(TAG, "updateService: " + regId + " " + t);
705 try {
706 if (t == null) return false;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700707 mNativeConnector.execute("mdnssd", "update", regId, t.size(), t.getRawData());
708 } catch(NativeDaemonConnectorException e) {
Irfan Sheriff817388e2012-04-11 14:52:19 -0700709 Slog.e(TAG, "Failed to updateServices " + e);
710 return false;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700711 }
Irfan Sheriff817388e2012-04-11 14:52:19 -0700712 return true;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700713 }
714
Irfan Sheriff817388e2012-04-11 14:52:19 -0700715 private boolean discoverServices(int discoveryId, String serviceType) {
716 if (DBG) Slog.d(TAG, "discoverServices: " + discoveryId + " " + serviceType);
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700717 try {
718 mNativeConnector.execute("mdnssd", "discover", discoveryId, serviceType);
719 } catch(NativeDaemonConnectorException e) {
Irfan Sheriff817388e2012-04-11 14:52:19 -0700720 Slog.e(TAG, "Failed to discoverServices " + e);
721 return false;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700722 }
Irfan Sheriff817388e2012-04-11 14:52:19 -0700723 return true;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700724 }
725
Irfan Sheriff817388e2012-04-11 14:52:19 -0700726 private boolean stopServiceDiscovery(int discoveryId) {
727 if (DBG) Slog.d(TAG, "stopServiceDiscovery: " + discoveryId);
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700728 try {
Irfan Sheriff817388e2012-04-11 14:52:19 -0700729 mNativeConnector.execute("mdnssd", "stop-discover", discoveryId);
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700730 } catch(NativeDaemonConnectorException e) {
Irfan Sheriff817388e2012-04-11 14:52:19 -0700731 Slog.e(TAG, "Failed to stopServiceDiscovery " + e);
732 return false;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700733 }
Irfan Sheriff817388e2012-04-11 14:52:19 -0700734 return true;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700735 }
736
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700737 private boolean resolveService(int resolveId, NsdServiceInfo service) {
Irfan Sheriff817388e2012-04-11 14:52:19 -0700738 if (DBG) Slog.d(TAG, "resolveService: " + resolveId + " " + service);
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700739 try {
Irfan Sheriff817388e2012-04-11 14:52:19 -0700740 mNativeConnector.execute("mdnssd", "resolve", resolveId, service.getServiceName(),
741 service.getServiceType(), "local.");
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700742 } catch(NativeDaemonConnectorException e) {
Irfan Sheriff817388e2012-04-11 14:52:19 -0700743 Slog.e(TAG, "Failed to resolveService " + e);
744 return false;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700745 }
Irfan Sheriff817388e2012-04-11 14:52:19 -0700746 return true;
747 }
748
749 private boolean stopResolveService(int resolveId) {
750 if (DBG) Slog.d(TAG, "stopResolveService: " + resolveId);
751 try {
752 mNativeConnector.execute("mdnssd", "stop-resolve", resolveId);
753 } catch(NativeDaemonConnectorException e) {
754 Slog.e(TAG, "Failed to stop resolve " + e);
755 return false;
756 }
757 return true;
758 }
759
760 private boolean getAddrInfo(int resolveId, String hostname) {
761 if (DBG) Slog.d(TAG, "getAdddrInfo: " + resolveId);
762 try {
763 mNativeConnector.execute("mdnssd", "getaddrinfo", resolveId, hostname);
764 } catch(NativeDaemonConnectorException e) {
765 Slog.e(TAG, "Failed to getAddrInfo " + e);
766 return false;
767 }
768 return true;
769 }
770
771 private boolean stopGetAddrInfo(int resolveId) {
772 if (DBG) Slog.d(TAG, "stopGetAdddrInfo: " + resolveId);
773 try {
774 mNativeConnector.execute("mdnssd", "stop-getaddrinfo", resolveId);
775 } catch(NativeDaemonConnectorException e) {
776 Slog.e(TAG, "Failed to stopGetAddrInfo " + e);
777 return false;
778 }
779 return true;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700780 }
781
782 @Override
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700783 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700784 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
785 != PackageManager.PERMISSION_GRANTED) {
786 pw.println("Permission Denial: can't dump ServiceDiscoverService from from pid="
787 + Binder.getCallingPid()
788 + ", uid=" + Binder.getCallingUid());
789 return;
790 }
791
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700792 for (ClientInfo client : mClients.values()) {
793 pw.println("Client Info");
794 pw.println(client);
795 }
796
797 mNsdStateMachine.dump(fd, pw, args);
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700798 }
Irfan Sheriff817388e2012-04-11 14:52:19 -0700799
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700800 /* arg2 on the source message has an id that needs to be retained in replies
801 * see NsdManager for details */
802 private Message obtainMessage(Message srcMsg) {
803 Message msg = Message.obtain();
804 msg.arg2 = srcMsg.arg2;
805 return msg;
Irfan Sheriff817388e2012-04-11 14:52:19 -0700806 }
807
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700808 private void replyToMessage(Message msg, int what) {
809 if (msg.replyTo == null) return;
810 Message dstMsg = obtainMessage(msg);
811 dstMsg.what = what;
812 mReplyChannel.replyToMessage(msg, dstMsg);
Irfan Sheriff817388e2012-04-11 14:52:19 -0700813 }
814
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700815 private void replyToMessage(Message msg, int what, int arg1) {
816 if (msg.replyTo == null) return;
817 Message dstMsg = obtainMessage(msg);
818 dstMsg.what = what;
819 dstMsg.arg1 = arg1;
820 mReplyChannel.replyToMessage(msg, dstMsg);
821 }
822
823 private void replyToMessage(Message msg, int what, Object obj) {
824 if (msg.replyTo == null) return;
825 Message dstMsg = obtainMessage(msg);
826 dstMsg.what = what;
827 dstMsg.obj = obj;
828 mReplyChannel.replyToMessage(msg, dstMsg);
Irfan Sheriff817388e2012-04-11 14:52:19 -0700829 }
830
831 /* Information tracked per client */
832 private class ClientInfo {
833
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700834 private static final int MAX_LIMIT = 10;
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700835 private final AsyncChannel mChannel;
836 private final Messenger mMessenger;
Irfan Sheriff817388e2012-04-11 14:52:19 -0700837 /* Remembers a resolved service until getaddrinfo completes */
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700838 private NsdServiceInfo mResolvedService;
839
840 /* A map from client id to unique id sent to mDns */
841 private SparseArray<Integer> mClientIds = new SparseArray<Integer>();
Irfan Sheriff817388e2012-04-11 14:52:19 -0700842
Dave Plattf31760c2014-03-07 14:48:22 -0800843 /* A map from client id to the type of the request we had received */
844 private SparseArray<Integer> mClientRequests = new SparseArray<Integer>();
845
Irfan Sheriff817388e2012-04-11 14:52:19 -0700846 private ClientInfo(AsyncChannel c, Messenger m) {
847 mChannel = c;
848 mMessenger = m;
Irfan Sheriff817388e2012-04-11 14:52:19 -0700849 if (DBG) Slog.d(TAG, "New client, channel: " + c + " messenger: " + m);
850 }
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700851
852 @Override
853 public String toString() {
854 StringBuffer sb = new StringBuffer();
855 sb.append("mChannel ").append(mChannel).append("\n");
856 sb.append("mMessenger ").append(mMessenger).append("\n");
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700857 sb.append("mResolvedService ").append(mResolvedService).append("\n");
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700858 for(int i = 0; i< mClientIds.size(); i++) {
Dave Plattf31760c2014-03-07 14:48:22 -0800859 int clientID = mClientIds.keyAt(i);
860 sb.append("clientId ").append(clientID).
861 append(" mDnsId ").append(mClientIds.valueAt(i)).
862 append(" type ").append(mClientRequests.get(clientID)).append("\n");
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700863 }
864 return sb.toString();
865 }
Dave Plattf31760c2014-03-07 14:48:22 -0800866
867 // Remove any pending requests from the global map when we get rid of a client,
868 // and send cancellations to the daemon.
869 private void expungeAllRequests() {
870 int globalId, clientId, i;
871 for (i = 0; i < mClientIds.size(); i++) {
872 clientId = mClientIds.keyAt(i);
873 globalId = mClientIds.valueAt(i);
874 mIdToClientInfoMap.remove(globalId);
875 if (DBG) Slog.d(TAG, "Terminating client-ID " + clientId +
876 " global-ID " + globalId + " type " + mClientRequests.get(clientId));
877 switch (mClientRequests.get(clientId)) {
878 case NsdManager.DISCOVER_SERVICES:
879 stopServiceDiscovery(globalId);
880 break;
881 case NsdManager.RESOLVE_SERVICE:
882 stopResolveService(globalId);
883 break;
884 case NsdManager.REGISTER_SERVICE:
885 unregisterService(globalId);
886 break;
887 default:
888 break;
889 }
890 }
891 mClientIds.clear();
892 mClientRequests.clear();
893 }
894
Irfan Sheriff817388e2012-04-11 14:52:19 -0700895 }
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700896}