blob: 768be7df410d644ad19e211a6d88bf90376b1e64 [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;
20import android.content.pm.PackageManager;
21import android.net.nsd.DnsSdServiceInfo;
22import android.net.nsd.DnsSdTxtRecord;
23import android.net.nsd.INsdManager;
24import android.net.nsd.NsdManager;
25import android.os.Binder;
26import android.os.Handler;
27import android.os.HandlerThread;
28import android.os.Message;
29import android.os.Messenger;
30import android.os.IBinder;
31import android.util.Slog;
32
33import java.io.FileDescriptor;
34import java.io.PrintWriter;
35import java.util.ArrayList;
36import java.util.concurrent.CountDownLatch;
37import java.util.List;
38
39import com.android.internal.app.IBatteryStats;
40import com.android.internal.telephony.TelephonyIntents;
41import com.android.internal.util.AsyncChannel;
42import com.android.server.am.BatteryStatsService;
43import com.android.server.NativeDaemonConnector.Command;
44import com.android.internal.R;
45
46/**
47 * Network Service Discovery Service handles remote service discovery operation requests by
48 * implementing the INsdManager interface.
49 *
50 * @hide
51 */
52public class NsdService extends INsdManager.Stub {
53 private static final String TAG = "NsdService";
54 private static final String MDNS_TAG = "mDnsConnector";
55
56 private static final boolean DBG = true;
57
58 private Context mContext;
59
60 /**
61 * Clients receiving asynchronous messages
62 */
63 private List<AsyncChannel> mClients = new ArrayList<AsyncChannel>();
64
65 private AsyncChannel mReplyChannel = new AsyncChannel();
66
67 /**
68 * Handles client(app) connections
69 */
70 private class AsyncServiceHandler extends Handler {
71
72 AsyncServiceHandler(android.os.Looper looper) {
73 super(looper);
74 }
75
76 @Override
77 public void handleMessage(Message msg) {
78 switch (msg.what) {
79 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
80 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
81 AsyncChannel c = (AsyncChannel) msg.obj;
82 if (DBG) Slog.d(TAG, "New client listening to asynchronous messages");
83 c.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED);
84 mClients.add(c);
85 } else {
86 Slog.e(TAG, "Client connection failure, error=" + msg.arg1);
87 }
88 break;
89 case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
90 if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
91 Slog.e(TAG, "Send failed, client connection lost");
92 } else {
93 if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1);
94 }
95 mClients.remove((AsyncChannel) msg.obj);
96 break;
97 case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
98 AsyncChannel ac = new AsyncChannel();
99 ac.connect(mContext, this, msg.replyTo);
100 break;
101 case NsdManager.DISCOVER_SERVICES:
102 if (DBG) Slog.d(TAG, "Discover services");
103 DnsSdServiceInfo s = (DnsSdServiceInfo) msg.obj;
104 discoverServices(1, s.getServiceType());
105 mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_STARTED);
106 break;
107 case NsdManager.STOP_DISCOVERY:
108 if (DBG) Slog.d(TAG, "Stop service discovery");
109 mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED);
110 break;
111 case NsdManager.REGISTER_SERVICE:
112 if (DBG) Slog.d(TAG, "Register service");
113 mReplyChannel.replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED);
114 break;
115 case NsdManager.UPDATE_SERVICE:
116 if (DBG) Slog.d(TAG, "Update service");
117 mReplyChannel.replyToMessage(msg, NsdManager.UPDATE_SERVICE_FAILED);
118 break;
119 default:
120 Slog.d(TAG, "NsdServicehandler.handleMessage ignoring msg=" + msg);
121 break;
122 }
123 }
124 }
125 private AsyncServiceHandler mAsyncServiceHandler;
126
127 private NativeDaemonConnector mNativeConnector;
128 private final CountDownLatch mNativeDaemonConnected = new CountDownLatch(1);
129
130 private NsdService(Context context) {
131 mContext = context;
132
133 HandlerThread nsdThread = new HandlerThread("NsdService");
134 nsdThread.start();
135 mAsyncServiceHandler = new AsyncServiceHandler(nsdThread.getLooper());
136
137 /*
138 mNativeConnector = new NativeDaemonConnector(new NativeCallbackReceiver(), "mdns", 10,
139 MDNS_TAG, 25);
140 Thread th = new Thread(mNativeConnector, MDNS_TAG);
141 th.start();
142 */
143 }
144
145 public static NsdService create(Context context) throws InterruptedException {
146 NsdService service = new NsdService(context);
147 /* service.mNativeDaemonConnected.await(); */
148 return service;
149 }
150
151 public Messenger getMessenger() {
152 return new Messenger(mAsyncServiceHandler);
153 }
154
155 /* These should be in sync with system/netd/mDnsResponseCode.h */
156 class NativeResponseCode {
157 public static final int SERVICE_FOUND = 101;
158 public static final int SERVICE_LOST = 102;
159 public static final int SERVICE_DISCOVERY_FAILED = 103;
160
161 public static final int SERVICE_REGISTERED = 104;
162 public static final int SERVICE_REGISTRATION_FAILED = 105;
163
164 public static final int SERVICE_UPDATED = 106;
165 public static final int SERVICE_UPDATE_FAILED = 107;
166
167 public static final int SERVICE_RESOLVED = 108;
168 public static final int SERVICE_RESOLUTION_FAILED = 109;
169 }
170
171
172 class NativeCallbackReceiver implements INativeDaemonConnectorCallbacks {
173 public void onDaemonConnected() {
174 mNativeDaemonConnected.countDown();
175 }
176
177 public boolean onEvent(int code, String raw, String[] cooked) {
178 switch (code) {
179 case NativeResponseCode.SERVICE_FOUND:
180 /* NNN uniqueId serviceName regType */
181 break;
182 case NativeResponseCode.SERVICE_LOST:
183 /* NNN uniqueId serviceName regType */
184 break;
185 case NativeResponseCode.SERVICE_DISCOVERY_FAILED:
186 /* NNN uniqueId errorCode */
187 break;
188 case NativeResponseCode.SERVICE_REGISTERED:
189 /* NNN regId serviceName regType */
190 break;
191 case NativeResponseCode.SERVICE_REGISTRATION_FAILED:
192 /* NNN regId errorCode */
193 break;
194 case NativeResponseCode.SERVICE_UPDATED:
195 /* NNN regId */
196 break;
197 case NativeResponseCode.SERVICE_UPDATE_FAILED:
198 /* NNN regId errorCode */
199 break;
200 case NativeResponseCode.SERVICE_RESOLVED:
201 /* NNN resolveId fullName hostName port txtlen txtdata */
202 break;
203 case NativeResponseCode.SERVICE_RESOLUTION_FAILED:
204 /* NNN resovleId errorCode */
205 break;
206 default:
207 break;
208 }
209 return false;
210 }
211 }
212
213 private void registerService(int regId, DnsSdServiceInfo service) {
214 try {
215 //Add txtlen and txtdata
216 mNativeConnector.execute("mdnssd", "register", regId, service.getServiceName(),
217 service.getServiceType(), service.getPort());
218 } catch(NativeDaemonConnectorException e) {
219 Slog.e(TAG, "Failed to execute registerService");
220 }
221 }
222
223 private void updateService(int regId, DnsSdTxtRecord t) {
224 try {
225 if (t == null) return;
226 mNativeConnector.execute("mdnssd", "update", regId, t.size(), t.getRawData());
227 } catch(NativeDaemonConnectorException e) {
228 Slog.e(TAG, "Failed to updateServices");
229 }
230 }
231
232 private void discoverServices(int discoveryId, String serviceType) {
233 try {
234 mNativeConnector.execute("mdnssd", "discover", discoveryId, serviceType);
235 } catch(NativeDaemonConnectorException e) {
236 Slog.e(TAG, "Failed to discoverServices");
237 }
238 }
239
240 private void stopServiceDiscovery(int discoveryId) {
241 try {
242 mNativeConnector.execute("mdnssd", "stopdiscover", discoveryId);
243 } catch(NativeDaemonConnectorException e) {
244 Slog.e(TAG, "Failed to stopServiceDiscovery");
245 }
246 }
247
248 private void resolveService(DnsSdServiceInfo service) {
249 try {
250 mNativeConnector.execute("mdnssd", "resolve", service.getServiceName(),
251 service.getServiceType());
252 } catch(NativeDaemonConnectorException e) {
253 Slog.e(TAG, "Failed to resolveService");
254 }
255 }
256
257 @Override
258 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
259 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
260 != PackageManager.PERMISSION_GRANTED) {
261 pw.println("Permission Denial: can't dump ServiceDiscoverService from from pid="
262 + Binder.getCallingPid()
263 + ", uid=" + Binder.getCallingUid());
264 return;
265 }
266
267 pw.println("Internal state:");
268 }
269}