NsdService.java revision ef12884da7c8844f8dd27cbc9c9980f685b73a2c
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2010 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * you may not use this file except in compliance with the License. 669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * You may obtain a copy of the License at 769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 1169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 1269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * See the License for the specific language governing permissions and 1469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver; 210795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopianimport android.content.Intent; 220795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopianimport android.content.pm.PackageManager; 23a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamathimport android.database.ContentObserver; 24f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kastenimport android.net.nsd.NsdServiceInfo; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.nsd.DnsSdTxtRecord; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.nsd.INsdManager; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.nsd.NsdManager; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Messenger; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.UserHandle; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Slog; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.SparseArray; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 36c6a410164e1fd728cf7873493baacca7bc29548dMark Salyzynimport java.io.FileDescriptor; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.UnsupportedEncodingException; 39c6a410164e1fd728cf7873493baacca7bc29548dMark Salyzynimport java.net.InetAddress; 40c6a410164e1fd728cf7873493baacca7bc29548dMark Salyzynimport java.util.HashMap; 41c6a410164e1fd728cf7873493baacca7bc29548dMark Salyzynimport java.util.List; 42c6a410164e1fd728cf7873493baacca7bc29548dMark Salyzynimport java.util.Locale; 436af763bec7c3f4d50fee8dd0046409bb8a7fe8f6Glenn Kastenimport java.util.Map; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.concurrent.CountDownLatch; 45957e58670baad8c5995f1368e3b5280f0dbd891fSan Mehat 46160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tateimport com.android.internal.util.AsyncChannel; 47a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehatimport com.android.internal.util.Protocol; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.util.State; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.util.StateMachine; 50160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tateimport com.android.server.NativeDaemonConnector.Command; 51160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate 52160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate/** 53160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate * Network Service Discovery Service handles remote service discovery operation requests by 54160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate * implementing the INsdManager interface. 55f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten * 56f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten * @hide 576793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten */ 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class NsdService extends INsdManager.Stub { 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "NsdService"; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String MDNS_TAG = "mDnsConnector"; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final boolean DBG = true; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Context mContext; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ContentResolver mContentResolver; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private NsdStateMachine mNsdStateMachine; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Clients receiving asynchronous messages 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private HashMap<Messenger, ClientInfo> mClients = new HashMap<Messenger, ClientInfo>(); 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* A map from unique id to client info */ 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SparseArray<ClientInfo> mIdToClientInfoMap= new SparseArray<ClientInfo>(); 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private AsyncChannel mReplyChannel = new AsyncChannel(); 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 786793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten private int INVALID_ID = 0; 79e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat private int mUniqueId = 1; 80e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat 81e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat private static final int BASE = Protocol.BASE_NSD_MANAGER; 82e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat private static final int CMD_TO_STRING_COUNT = NsdManager.RESOLVE_SERVICE - BASE + 1; 83e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT]; 84e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat 85e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat static { 86e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat sCmdToString[NsdManager.DISCOVER_SERVICES - BASE] = "DISCOVER"; 87e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat sCmdToString[NsdManager.STOP_DISCOVERY - BASE] = "STOP-DISCOVER"; 88e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat sCmdToString[NsdManager.REGISTER_SERVICE - BASE] = "REGISTER"; 89e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat sCmdToString[NsdManager.UNREGISTER_SERVICE - BASE] = "UNREGISTER"; 90e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat sCmdToString[NsdManager.RESOLVE_SERVICE - BASE] = "RESOLVE"; 91e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat } 92e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat 93e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat private static String cmdToString(int cmd) { 94e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat cmd -= BASE; 95e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat if ((cmd >= 0) && (cmd < sCmdToString.length)) { 96e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat return sCmdToString[cmd]; 97e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat } else { 98e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat return null; 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes private class NsdStateMachine extends StateMachine { 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final DefaultState mDefaultState = new DefaultState(); 10569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes private final DisabledState mDisabledState = new DisabledState(); 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final EnabledState mEnabledState = new EnabledState(); 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected String getWhatToString(int what) { 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return cmdToString(what); 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Observes the NSD on/off setting, and takes action when changed. 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void registerForNsdSetting() { 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContentObserver contentObserver = new ContentObserver(this.getHandler()) { 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onChange(boolean selfChange) { 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isNsdEnabled()) { 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNsdStateMachine.sendMessage(NsdManager.ENABLE); 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNsdStateMachine.sendMessage(NsdManager.DISABLE); 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.getContentResolver().registerContentObserver( 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.Global.getUriFor(Settings.Global.NSD_ON), 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project false, contentObserver); 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes NsdStateMachine(String name) { 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(name); 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project addState(mDefaultState); 13669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes addState(mDisabledState, mDefaultState); 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project addState(mEnabledState, mDefaultState); 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isNsdEnabled()) { 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setInitialState(mEnabledState); 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setInitialState(mDisabledState); 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setLogRecSize(25); 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project registerForNsdSetting(); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class DefaultState extends State { 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean processMessage(Message msg) { 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ClientInfo cInfo = null; 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (msg.what) { 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AsyncChannel c = (AsyncChannel) msg.obj; 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) Slog.d(TAG, "New client listening to asynchronous messages"); 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED); 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cInfo = new ClientInfo(c, msg.replyTo); 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mClients.put(msg.replyTo, cInfo); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Slog.e(TAG, "Client connection failure, error=" + msg.arg1); 161f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten } 162e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat break; 163c6a410164e1fd728cf7873493baacca7bc29548dMark Salyzyn case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 164f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten switch (msg.arg1) { 165f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten case AsyncChannel.STATUS_SEND_UNSUCCESSFUL: 166887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn Slog.e(TAG, "Send failed, client connection lost"); 167f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten break; 168e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat case AsyncChannel.STATUS_REMOTE_DISCONNECTION: 169e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat if (DBG) Slog.d(TAG, "Client disconnected"); 170e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat break; 17169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes default: 1723e458241d9930465a20a861ecb42744355d48e48San Mehat if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1); 173c6a410164e1fd728cf7873493baacca7bc29548dMark Salyzyn break; 1743e458241d9930465a20a861ecb42744355d48e48San Mehat } 1753e458241d9930465a20a861ecb42744355d48e48San Mehat cInfo = mClients.get(msg.replyTo); 1763e458241d9930465a20a861ecb42744355d48e48San Mehat if (cInfo != null) { 1773e458241d9930465a20a861ecb42744355d48e48San Mehat cInfo.expungeAllRequests(); 1783e458241d9930465a20a861ecb42744355d48e48San Mehat mClients.remove(msg.replyTo); 179f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten } 1806793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten //Last client 1813e458241d9930465a20a861ecb42744355d48e48San Mehat if (mClients.size() == 0) { 1823e458241d9930465a20a861ecb42744355d48e48San Mehat stopMDnsDaemon(); 1833e458241d9930465a20a861ecb42744355d48e48San Mehat } 184f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten break; 185f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: 186f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten AsyncChannel ac = new AsyncChannel(); 187f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten ac.connect(mContext, getHandler(), msg.replyTo); 188f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten break; 189f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten case NsdManager.DISCOVER_SERVICES: 190f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, 191a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat NsdManager.FAILURE_INTERNAL_ERROR); 192a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat break; 193a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat case NsdManager.STOP_DISCOVERY: 194a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, 195a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat NsdManager.FAILURE_INTERNAL_ERROR); 196a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat break; 197a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat case NsdManager.REGISTER_SERVICE: 198a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, 199a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat NsdManager.FAILURE_INTERNAL_ERROR); 200a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat break; 201a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat case NsdManager.UNREGISTER_SERVICE: 202a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, 203a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat NsdManager.FAILURE_INTERNAL_ERROR); 20469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes break; 205f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten case NsdManager.RESOLVE_SERVICE: 2065baa3a62a97544669fba6d65a11c07f252e654ddSteve Block replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, 207a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat NsdManager.FAILURE_INTERNAL_ERROR); 2085baa3a62a97544669fba6d65a11c07f252e654ddSteve Block break; 209a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat case NsdManager.NATIVE_DAEMON_EVENT: 210a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat default: 2113e458241d9930465a20a861ecb42744355d48e48San Mehat Slog.e(TAG, "Unhandled " + msg); 2123e458241d9930465a20a861ecb42744355d48e48San Mehat return NOT_HANDLED; 2131fd0ec738b0a2b97cc28701aa37b1a9869afc684San Mehat } 2141fd0ec738b0a2b97cc28701aa37b1a9869afc684San Mehat return HANDLED; 2156793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten } 2163e458241d9930465a20a861ecb42744355d48e48San Mehat } 2173e458241d9930465a20a861ecb42744355d48e48San Mehat 2183e458241d9930465a20a861ecb42744355d48e48San Mehat class DisabledState extends State { 2193e458241d9930465a20a861ecb42744355d48e48San Mehat @Override 2207e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat public void enter() { 2217e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat sendNsdStateChangeBroadcast(false); 2227e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat } 2233e458241d9930465a20a861ecb42744355d48e48San Mehat 2243e458241d9930465a20a861ecb42744355d48e48San Mehat @Override 2257e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat public boolean processMessage(Message msg) { 2267e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat switch (msg.what) { 2277e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat case NsdManager.ENABLE: 2283762c311729fe9f3af085c14c5c1fb471d994c03Steve Block transitionTo(mEnabledState); 2297e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat break; 2307e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat default: 2311fd0ec738b0a2b97cc28701aa37b1a9869afc684San Mehat return NOT_HANDLED; 23207b0465095bd9ab3412caefa4fcacbdc3825c64bGlenn Kasten } 23307b0465095bd9ab3412caefa4fcacbdc3825c64bGlenn Kasten return HANDLED; 23407b0465095bd9ab3412caefa4fcacbdc3825c64bGlenn Kasten } 23507b0465095bd9ab3412caefa4fcacbdc3825c64bGlenn Kasten } 23607b0465095bd9ab3412caefa4fcacbdc3825c64bGlenn Kasten 23707b0465095bd9ab3412caefa4fcacbdc3825c64bGlenn Kasten class EnabledState extends State { 23807b0465095bd9ab3412caefa4fcacbdc3825c64bGlenn Kasten @Override 23907b0465095bd9ab3412caefa4fcacbdc3825c64bGlenn Kasten public void enter() { 24007b0465095bd9ab3412caefa4fcacbdc3825c64bGlenn Kasten sendNsdStateChangeBroadcast(true); 2417e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat if (mClients.size() > 0) { 24207b0465095bd9ab3412caefa4fcacbdc3825c64bGlenn Kasten startMDnsDaemon(); 243f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten } 244f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten } 245f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten 246f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten @Override 2477e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat public void exit() { 24869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes if (mClients.size() > 0) { 249f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten stopMDnsDaemon(); 250f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten } 251f1b56449f58963e4f0473d5e26961f68c31759f4Glenn Kasten } 2520a42b811aea490a9a605b75f0320101f6eafd283San Mehat 253242d65bf9faf1d2bc3468490e510551140e23462San Mehat private boolean requestLimitReached(ClientInfo clientInfo) { 2543e458241d9930465a20a861ecb42744355d48e48San Mehat if (clientInfo.mClientIds.size() >= ClientInfo.MAX_LIMIT) { 2553e458241d9930465a20a861ecb42744355d48e48San Mehat if (DBG) Slog.d(TAG, "Exceeded max outstanding requests " + clientInfo); 2563e458241d9930465a20a861ecb42744355d48e48San Mehat return true; 2573e458241d9930465a20a861ecb42744355d48e48San Mehat } 2589e57c414f39e1a31349bc215635fdcfaf1902ceeJeff Sharkey return false; 2599e57c414f39e1a31349bc215635fdcfaf1902ceeJeff Sharkey } 2609e57c414f39e1a31349bc215635fdcfaf1902ceeJeff Sharkey 2619e57c414f39e1a31349bc215635fdcfaf1902ceeJeff Sharkey private void storeRequestMap(int clientId, int globalId, ClientInfo clientInfo, int what) { 2629e57c414f39e1a31349bc215635fdcfaf1902ceeJeff Sharkey clientInfo.mClientIds.put(clientId, globalId); 2639e57c414f39e1a31349bc215635fdcfaf1902ceeJeff Sharkey clientInfo.mClientRequests.put(clientId, what); 2649e57c414f39e1a31349bc215635fdcfaf1902ceeJeff Sharkey mIdToClientInfoMap.put(globalId, clientInfo); 2659e57c414f39e1a31349bc215635fdcfaf1902ceeJeff Sharkey } 2669e57c414f39e1a31349bc215635fdcfaf1902ceeJeff Sharkey 267160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) { 268160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate clientInfo.mClientIds.remove(clientId); 269160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate clientInfo.mClientRequests.remove(clientId); 270160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate mIdToClientInfoMap.remove(globalId); 27171f2cf116aab893e224056c38ab146bd1538dd3eSteve Block } 272160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate 273160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate @Override 274160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate public boolean processMessage(Message msg) { 275160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate ClientInfo clientInfo; 276160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate NsdServiceInfo servInfo; 277160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate boolean result = HANDLED; 278160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate int id; 279160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate switch (msg.what) { 280160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 281160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate //First client 282160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL && 283160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate mClients.size() == 0) { 2846793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten startMDnsDaemon(); 2856793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten } 2866793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten result = NOT_HANDLED; 287cc767191cfb675f744e0165608b0a4196aba2b37Glenn Kasten break; 2886793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 2896793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten result = NOT_HANDLED; 2906793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten break; 2916793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten case NsdManager.DISABLE: 2926793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten //TODO: cleanup clients 2936793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten transitionTo(mDisabledState); 294cc767191cfb675f744e0165608b0a4196aba2b37Glenn Kasten break; 295cc767191cfb675f744e0165608b0a4196aba2b37Glenn Kasten case NsdManager.DISCOVER_SERVICES: 296cc767191cfb675f744e0165608b0a4196aba2b37Glenn Kasten if (DBG) Slog.d(TAG, "Discover services"); 2976793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten servInfo = (NsdServiceInfo) msg.obj; 2986793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten clientInfo = mClients.get(msg.replyTo); 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (requestLimitReached(clientInfo)) { 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, 302160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate NsdManager.FAILURE_MAX_LIMIT); 303160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate break; 304160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate } 305160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate 306160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate id = getUniqueId(); 307160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate if (discoverServices(id, servInfo.getServiceType())) { 308160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate if (DBG) { 3093762c311729fe9f3af085c14c5c1fb471d994c03Steve Block Slog.d(TAG, "Discover " + msg.arg2 + " " + id + 310160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate servInfo.getServiceType()); 311160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate } 312160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate storeRequestMap(msg.arg2, id, clientInfo, msg.what); 313160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate replyToMessage(msg, NsdManager.DISCOVER_SERVICES_STARTED, servInfo); 314160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate } else { 315160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate stopServiceDiscovery(id); 316160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, 317887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn NsdManager.FAILURE_INTERNAL_ERROR); 318887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn } 319887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn break; 3206793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten case NsdManager.STOP_DISCOVERY: 321887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn if (DBG) Slog.d(TAG, "Stop service discovery"); 3226793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten clientInfo = mClients.get(msg.replyTo); 323887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 32569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes id = clientInfo.mClientIds.get(msg.arg2).intValue(); 326c6a410164e1fd728cf7873493baacca7bc29548dMark Salyzyn } catch (NullPointerException e) { 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NsdManager.FAILURE_INTERNAL_ERROR); 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeRequestMap(msg.arg2, id, clientInfo); 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (stopServiceDiscovery(id)) { 3336d4b1e24aef5b74b40de4d8f6e63c21874ce8e3aElliott Hughes replyToMessage(msg, NsdManager.STOP_DISCOVERY_SUCCEEDED); 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NsdManager.FAILURE_INTERNAL_ERROR); 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case NsdManager.REGISTER_SERVICE: 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) Slog.d(TAG, "Register service"); 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clientInfo = mClients.get(msg.replyTo); 3426793ac943afeb16642f477c43ddfd27e498db37bGlenn Kasten if (requestLimitReached(clientInfo)) { 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, 344c6a410164e1fd728cf7873493baacca7bc29548dMark Salyzyn NsdManager.FAILURE_MAX_LIMIT); 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project id = getUniqueId(); 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (registerService(id, (NsdServiceInfo) msg.obj)) { 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) Slog.d(TAG, "Register " + msg.arg2 + " " + id); 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project storeRequestMap(msg.arg2, id, clientInfo, msg.what); 35210e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown // Return success after mDns reports success 35310e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown } else { 35410e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown unregisterService(id); 35510e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, 35610e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown NsdManager.FAILURE_INTERNAL_ERROR); 35710e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown } 35810e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown break; 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case NsdManager.UNREGISTER_SERVICE: 36010e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown if (DBG) Slog.d(TAG, "unregister service"); 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clientInfo = mClients.get(msg.replyTo); 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project id = clientInfo.mClientIds.get(msg.arg2).intValue(); 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NullPointerException e) { 3655534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, 3665534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand NsdManager.FAILURE_INTERNAL_ERROR); 3675534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand break; 3685534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand } 3695534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand removeRequestMap(msg.arg2, id, clientInfo); 3705534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand if (unregisterService(id)) { 3715534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_SUCCEEDED); 3725534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand } else { 3735534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, 3745534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand NsdManager.FAILURE_INTERNAL_ERROR); 3755534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand } 3765534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand break; 3775534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand case NsdManager.RESOLVE_SERVICE: 3785534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand if (DBG) Slog.d(TAG, "Resolve service"); 3795534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand servInfo = (NsdServiceInfo) msg.obj; 3805534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand clientInfo = mClients.get(msg.replyTo); 3815534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand 3825534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand 383c6a410164e1fd728cf7873493baacca7bc29548dMark Salyzyn if (clientInfo.mResolvedService != null) { 3845534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, 3855534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand NsdManager.FAILURE_ALREADY_ACTIVE); 3865534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand break; 3875534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand } 3885534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand 3895534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand id = getUniqueId(); 3905534ba91ac0a0c9af822af62bcf92e2c5a8d6ec8Rom Lemarchand if (resolveService(id, servInfo)) { 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clientInfo.mResolvedService = new NsdServiceInfo(); 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project storeRequestMap(msg.arg2, id, clientInfo, msg.what); 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 39469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NsdManager.FAILURE_INTERNAL_ERROR); 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 39769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes break; 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case NsdManager.NATIVE_DAEMON_EVENT: 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NativeEvent event = (NativeEvent) msg.obj; 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!handleNativeEvent(event.code, event.raw, event.cooked)) { 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = NOT_HANDLED; 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = NOT_HANDLED; 406a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath break; 407a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath } 408a23fcd7be8e40078a913b1a99222cdd89229e67bNarayan Kamath return result; 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean handleNativeEvent(int code, String raw, String[] cooked) { 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean handled = true; 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NsdServiceInfo servInfo; 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int id = Integer.parseInt(cooked[1]); 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ClientInfo clientInfo = mIdToClientInfoMap.get(id); 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (clientInfo == null) { 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Slog.e(TAG, "Unique id with no client mapping: " + id); 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handled = false; 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return handled; 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* This goes in response as msg.arg2 */ 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int clientId = clientInfo.getClientId(id); 424c6a410164e1fd728cf7873493baacca7bc29548dMark Salyzyn if (clientId < 0) { 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This can happen because of race conditions. For example, 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // SERVICE_FOUND may race with STOP_SERVICE_DISCOVERY, 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // and we may get in this situation. 428c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes Slog.d(TAG, "Notification for a listener that is no longer active: " + id); 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handled = false; 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return handled; 43169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes } 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4338564c8da817a845353d213acd8636b76f567b234Steve Block switch (code) { 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case NativeResponseCode.SERVICE_FOUND: 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* NNN uniqueId serviceName regType domain */ 43669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes if (DBG) Slog.d(TAG, "SERVICE_FOUND Raw: " + raw); 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project servInfo = new NsdServiceInfo(cooked[2], cooked[3]); 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clientInfo.mChannel.sendMessage(NsdManager.SERVICE_FOUND, 0, 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clientId, servInfo); 44069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes break; 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case NativeResponseCode.SERVICE_LOST: 4428564c8da817a845353d213acd8636b76f567b234Steve Block /* NNN uniqueId serviceName regType domain */ 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) Slog.d(TAG, "SERVICE_LOST Raw: " + raw); 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project servInfo = new NsdServiceInfo(cooked[2], cooked[3]); 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clientInfo.mChannel.sendMessage(NsdManager.SERVICE_LOST, 0, 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clientId, servInfo); 447c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes break; 4480bca96bcbfe559f9330a01f723c5c9cba51ec05aMarco Nelissen case NativeResponseCode.SERVICE_DISCOVERY_FAILED: 44969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes /* NNN uniqueId errorCode */ 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) Slog.d(TAG, "SERVICE_DISC_FAILED Raw: " + raw); 45159325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn clientInfo.mChannel.sendMessage(NsdManager.DISCOVER_SERVICES_FAILED, 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NsdManager.FAILURE_INTERNAL_ERROR, clientId); 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case NativeResponseCode.SERVICE_REGISTERED: 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* NNN regId serviceName regType */ 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) Slog.d(TAG, "SERVICE_REGISTERED Raw: " + raw); 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project servInfo = new NsdServiceInfo(cooked[2], null); 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_SUCCEEDED, 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project id, clientId, servInfo); 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case NativeResponseCode.SERVICE_REGISTRATION_FAILED: 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* NNN regId errorCode */ 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) Slog.d(TAG, "SERVICE_REGISTER_FAILED Raw: " + raw); 4640bca96bcbfe559f9330a01f723c5c9cba51ec05aMarco Nelissen clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_FAILED, 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NsdManager.FAILURE_INTERNAL_ERROR, clientId); 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case NativeResponseCode.SERVICE_UPDATED: 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* NNN regId */ 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case NativeResponseCode.SERVICE_UPDATE_FAILED: 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* NNN regId errorCode */ 47269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes break; 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case NativeResponseCode.SERVICE_RESOLVED: 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* NNN resolveId fullName hostName port txtlen txtdata */ 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) Slog.d(TAG, "SERVICE_RESOLVED Raw: " + raw); 47659325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn int index = 0; 47759325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn while (index < cooked[2].length() && cooked[2].charAt(index) != '.') { 47859325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn if (cooked[2].charAt(index) == '\\') { 479c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes ++index; 48059325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn } 48159325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn ++index; 48259325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn } 48359325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn if (index >= cooked[2].length()) { 48459325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn Slog.e(TAG, "Invalid service found " + raw); 48559325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn break; 486c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes } 48759325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn String name = cooked[2].substring(0, index); 48859325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn String rest = cooked[2].substring(index); 48959325eb31f25704bb88c348160bb69e7c1aa3b48Dianne Hackborn String type = rest.replace(".local.", ""); 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project name = unescape(name); 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4936215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block clientInfo.mResolvedService.setServiceName(name); 49469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes clientInfo.mResolvedService.setServiceType(type); 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4])); 49669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stopResolveService(id); 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeRequestMap(clientId, id, clientInfo); 49969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int id2 = getUniqueId(); 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getAddrInfo(id2, cooked[3])) { 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project storeRequestMap(clientId, id2, clientInfo, NsdManager.RESOLVE_SERVICE); 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NsdManager.FAILURE_INTERNAL_ERROR, clientId); 50669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes clientInfo.mResolvedService = null; 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case NativeResponseCode.SERVICE_RESOLUTION_FAILED: 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* NNN resolveId errorCode */ 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) Slog.d(TAG, "SERVICE_RESOLVE_FAILED Raw: " + raw); 51269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes stopResolveService(id); 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeRequestMap(clientId, id, clientInfo); 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clientInfo.mResolvedService = null; 51569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NsdManager.FAILURE_INTERNAL_ERROR, clientId); 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case NativeResponseCode.SERVICE_GET_ADDR_FAILED: 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* NNN resolveId errorCode */ 5206215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block stopGetAddrInfo(id); 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeRequestMap(clientId, id, clientInfo); 52269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes clientInfo.mResolvedService = null; 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) Slog.d(TAG, "SERVICE_RESOLVE_FAILED Raw: " + raw); 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NsdManager.FAILURE_INTERNAL_ERROR, clientId); 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS: 52869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes /* NNN resolveId hostname ttl addr */ 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) Slog.d(TAG, "SERVICE_GET_ADDR_SUCCESS Raw: " + raw); 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clientInfo.mResolvedService.setHost(InetAddress.getByName(cooked[4])); 53269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_SUCCEEDED, 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 0, clientId, clientInfo.mResolvedService); 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (java.net.UnknownHostException e) { 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NsdManager.FAILURE_INTERNAL_ERROR, clientId); 53769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes } 538c6a410164e1fd728cf7873493baacca7bc29548dMark Salyzyn stopGetAddrInfo(id); 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeRequestMap(clientId, id, clientInfo); 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clientInfo.mResolvedService = null; 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 54269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes default: 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handled = false; 54469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes break; 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return handled; 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 55069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String unescape(String s) { 5528564c8da817a845353d213acd8636b76f567b234Steve Block StringBuilder sb = new StringBuilder(s.length()); 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < s.length(); ++i) { 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = s.charAt(i); 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c == '\\') { 55669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes if (++i >= s.length()) { 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Slog.e(TAG, "Unexpected end of escape sequence in: " + s); 55869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes break; 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c = s.charAt(i); 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c != '.' && c != '\\') { 5626215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block if (i + 2 >= s.length()) { 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Slog.e(TAG, "Unexpected end of escape sequence in: " + s); 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c = (char) ((c-'0') * 100 + (s.charAt(i+1)-'0') * 10 + (s.charAt(i+2)-'0')); 567add868cebaf62cffe96e79764ea0b7f2320a03ebAmith Yamasani i += 2; 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(c); 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sb.toString(); 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private NativeDaemonConnector mNativeConnector; 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final CountDownLatch mNativeDaemonConnected = new CountDownLatch(1); 577c6a410164e1fd728cf7873493baacca7bc29548dMark Salyzyn 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private NsdService(Context context) { 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContentResolver = context.getContentResolver(); 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNativeConnector = new NativeDaemonConnector(new NativeCallbackReceiver(), "mdns", 10, 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MDNS_TAG, 25, null); 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNsdStateMachine = new NsdStateMachine(TAG); 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNsdStateMachine.start(); 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Thread th = new Thread(mNativeConnector, MDNS_TAG); 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project th.start(); 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 59169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static NsdService create(Context context) throws InterruptedException { 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project NsdService service = new NsdService(context); 5948564c8da817a845353d213acd8636b76f567b234Steve Block service.mNativeDaemonConnected.await(); 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return service; 59669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes } 5976215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Messenger getMessenger() { 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET, 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "NsdService"); 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new Messenger(mNsdStateMachine.getHandler()); 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setEnabled(boolean enable) { 60569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL, 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "NsdService"); 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Settings.Global.putInt(mContentResolver, Settings.Global.NSD_ON, enable ? 1 : 0); 60869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes if (enable) { 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNsdStateMachine.sendMessage(NsdManager.ENABLE); 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNsdStateMachine.sendMessage(NsdManager.DISABLE); 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 61469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void sendNsdStateChangeBroadcast(boolean enabled) { 61669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes final Intent intent = new Intent(NsdManager.ACTION_NSD_STATE_CHANGED); 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 61869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes if (enabled) { 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intent.putExtra(NsdManager.EXTRA_NSD_STATE, NsdManager.NSD_STATE_ENABLED); 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project intent.putExtra(NsdManager.EXTRA_NSD_STATE, NsdManager.NSD_STATE_DISABLED); 62269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes } 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean isNsdEnabled() { 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean ret = Settings.Global.getInt(mContentResolver, Settings.Global.NSD_ON, 1) == 1; 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) Slog.d(TAG, "Network service discovery enabled " + ret); 62969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes return ret; 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 63169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int getUniqueId() { 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (++mUniqueId == INVALID_ID) return ++mUniqueId; 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mUniqueId; 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* These should be in sync with system/netd/server/ResponseCode.h */ 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class NativeResponseCode { 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int SERVICE_DISCOVERY_FAILED = 602; 64069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes public static final int SERVICE_FOUND = 603; 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int SERVICE_LOST = 604; 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6436215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block public static final int SERVICE_REGISTRATION_FAILED = 605; 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int SERVICE_REGISTERED = 606; 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int SERVICE_RESOLUTION_FAILED = 607; 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int SERVICE_RESOLVED = 608; 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int SERVICE_UPDATED = 609; 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int SERVICE_UPDATE_FAILED = 610; 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int SERVICE_GET_ADDR_FAILED = 611; 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int SERVICE_GET_ADDR_SUCCESS = 612; 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class NativeEvent { 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int code; 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final String raw; 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final String[] cooked; 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 66169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes NativeEvent(int code, String raw, String[] cooked) { 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.code = code; 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.raw = raw; 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.cooked = cooked; 66569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes } 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 66769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class NativeCallbackReceiver implements INativeDaemonConnectorCallbacks { 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onDaemonConnected() { 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNativeDaemonConnected.countDown(); 67169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes } 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onCheckHoldWakeLock(int code) { 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 67669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onEvent(int code, String raw, String[] cooked) { 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: NDC translates a message to a callback, we could enhance NDC to 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // directly interact with a state machine through messages 68069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes NativeEvent event = new NativeEvent(code, raw, cooked); 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNsdStateMachine.sendMessage(NsdManager.NATIVE_DAEMON_EVENT, event); 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean startMDnsDaemon() { 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) Slog.d(TAG, "startMDnsDaemon"); 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNativeConnector.execute("mdnssd", "start-service"); 69013ac041b9f21043bc7c848a743be618bfd7a67e9Dianne Hackborn } catch(NativeDaemonConnectorException e) { 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Slog.e(TAG, "Failed to start daemon" + e); 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 696c64edde69d18498fb2954f71a546357b07ab996aEvan Millar 69769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes private boolean stopMDnsDaemon() { 698c64edde69d18498fb2954f71a546357b07ab996aEvan Millar if (DBG) Slog.d(TAG, "stopMDnsDaemon"); 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 70069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes mNativeConnector.execute("mdnssd", "stop-service"); 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch(NativeDaemonConnectorException e) { 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Slog.e(TAG, "Failed to start daemon" + e); 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 70569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes return true; 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean registerService(int regId, NsdServiceInfo service) { 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) Slog.d(TAG, "registerService: " + regId + " " + service); 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Command cmd = new Command("mdnssd", "register", regId, service.getServiceName(), 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project service.getServiceType(), service.getPort()); 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Add TXT records as additional arguments. 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Map<String, byte[]> txtRecords = service.getAttributes(); 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String key : txtRecords.keySet()) { 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: Send encoded TXT record as bytes once NDC/netd supports binary data. 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cmd.appendArg(String.format(Locale.US, "%s=%s", key, 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new String(txtRecords.get(key), "UTF_8"))); 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (UnsupportedEncodingException e) { 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Slog.e(TAG, "Failed to encode txtRecord " + e); 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 726c64edde69d18498fb2954f71a546357b07ab996aEvan Millar mNativeConnector.execute(cmd); 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch(NativeDaemonConnectorException e) { 72869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes Slog.e(TAG, "Failed to execute registerService " + e); 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 73069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes } 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 73213ac041b9f21043bc7c848a743be618bfd7a67e9Dianne Hackborn } 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean unregisterService(int regId) { 73513ac041b9f21043bc7c848a743be618bfd7a67e9Dianne Hackborn if (DBG) Slog.d(TAG, "unregisterService: " + regId); 73613ac041b9f21043bc7c848a743be618bfd7a67e9Dianne Hackborn try { 73713ac041b9f21043bc7c848a743be618bfd7a67e9Dianne Hackborn mNativeConnector.execute("mdnssd", "stop-register", regId); 73813ac041b9f21043bc7c848a743be618bfd7a67e9Dianne Hackborn } catch(NativeDaemonConnectorException e) { 73913ac041b9f21043bc7c848a743be618bfd7a67e9Dianne Hackborn Slog.e(TAG, "Failed to execute unregisterService " + e); 74013ac041b9f21043bc7c848a743be618bfd7a67e9Dianne Hackborn return false; 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 744c64edde69d18498fb2954f71a546357b07ab996aEvan Millar 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean updateService(int regId, DnsSdTxtRecord t) { 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) Slog.d(TAG, "updateService: " + regId + " " + t); 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 74869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes if (t == null) return false; 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNativeConnector.execute("mdnssd", "update", regId, t.size(), t.getRawData()); 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch(NativeDaemonConnectorException e) { 751c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes Slog.e(TAG, "Failed to updateServices " + e); 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 75613ac041b9f21043bc7c848a743be618bfd7a67e9Dianne Hackborn 75713ac041b9f21043bc7c848a743be618bfd7a67e9Dianne Hackborn private boolean discoverServices(int discoveryId, String serviceType) { 75813ac041b9f21043bc7c848a743be618bfd7a67e9Dianne Hackborn if (DBG) Slog.d(TAG, "discoverServices: " + discoveryId + " " + serviceType); 75913ac041b9f21043bc7c848a743be618bfd7a67e9Dianne Hackborn try { 76013ac041b9f21043bc7c848a743be618bfd7a67e9Dianne Hackborn mNativeConnector.execute("mdnssd", "discover", discoveryId, serviceType); 76113ac041b9f21043bc7c848a743be618bfd7a67e9Dianne Hackborn } catch(NativeDaemonConnectorException e) { 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Slog.e(TAG, "Failed to discoverServices " + e); 763c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes return false; 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean stopServiceDiscovery(int discoveryId) { 76969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes if (DBG) Slog.d(TAG, "stopServiceDiscovery: " + discoveryId); 770c64edde69d18498fb2954f71a546357b07ab996aEvan Millar try { 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNativeConnector.execute("mdnssd", "stop-discover", discoveryId); 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch(NativeDaemonConnectorException e) { 773c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes Slog.e(TAG, "Failed to stopServiceDiscovery " + e); 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 77869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 779c6a410164e1fd728cf7873493baacca7bc29548dMark Salyzyn private boolean resolveService(int resolveId, NsdServiceInfo service) { 78069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes if (DBG) Slog.d(TAG, "resolveService: " + resolveId + " " + service); 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNativeConnector.execute("mdnssd", "resolve", resolveId, service.getServiceName(), 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project service.getServiceType(), "local."); 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch(NativeDaemonConnectorException e) { 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Slog.e(TAG, "Failed to resolveService " + e); 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean stopResolveService(int resolveId) { 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) Slog.d(TAG, "stopResolveService: " + resolveId); 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNativeConnector.execute("mdnssd", "stop-resolve", resolveId); 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch(NativeDaemonConnectorException e) { 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Slog.e(TAG, "Failed to stop resolve " + e); 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 80069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes } 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean getAddrInfo(int resolveId, String hostname) { 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) Slog.d(TAG, "getAdddrInfo: " + resolveId); 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNativeConnector.execute("mdnssd", "getaddrinfo", resolveId, hostname); 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch(NativeDaemonConnectorException e) { 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Slog.e(TAG, "Failed to getAddrInfo " + e); 80869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes return false; 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 812c64edde69d18498fb2954f71a546357b07ab996aEvan Millar 81369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes private boolean stopGetAddrInfo(int resolveId) { 814c64edde69d18498fb2954f71a546357b07ab996aEvan Millar if (DBG) Slog.d(TAG, "stopGetAdddrInfo: " + resolveId); 815c64edde69d18498fb2954f71a546357b07ab996aEvan Millar try { 816c64edde69d18498fb2954f71a546357b07ab996aEvan Millar mNativeConnector.execute("mdnssd", "stop-getaddrinfo", resolveId); 817c64edde69d18498fb2954f71a546357b07ab996aEvan Millar } catch(NativeDaemonConnectorException e) { 81869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes Slog.e(TAG, "Failed to stopGetAddrInfo " + e); 81969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes return false; 820c64edde69d18498fb2954f71a546357b07ab996aEvan Millar } 82169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes return true; 822c64edde69d18498fb2954f71a546357b07ab996aEvan Millar } 82369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes 824c64edde69d18498fb2954f71a546357b07ab996aEvan Millar @Override 825c64edde69d18498fb2954f71a546357b07ab996aEvan Millar public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 826c64edde69d18498fb2954f71a546357b07ab996aEvan Millar if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 827c64edde69d18498fb2954f71a546357b07ab996aEvan Millar != PackageManager.PERMISSION_GRANTED) { 828c64edde69d18498fb2954f71a546357b07ab996aEvan Millar pw.println("Permission Denial: can't dump ServiceDiscoverService from from pid=" 829c64edde69d18498fb2954f71a546357b07ab996aEvan Millar + Binder.getCallingPid() 830c64edde69d18498fb2954f71a546357b07ab996aEvan Millar + ", uid=" + Binder.getCallingUid()); 831c64edde69d18498fb2954f71a546357b07ab996aEvan Millar return; 83269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes } 833c64edde69d18498fb2954f71a546357b07ab996aEvan Millar 834c64edde69d18498fb2954f71a546357b07ab996aEvan Millar for (ClientInfo client : mClients.values()) { 835c64edde69d18498fb2954f71a546357b07ab996aEvan Millar pw.println("Client Info"); 836c64edde69d18498fb2954f71a546357b07ab996aEvan Millar pw.println(client); 837c64edde69d18498fb2954f71a546357b07ab996aEvan Millar } 838c64edde69d18498fb2954f71a546357b07ab996aEvan Millar 839c64edde69d18498fb2954f71a546357b07ab996aEvan Millar mNsdStateMachine.dump(fd, pw, args); 840c64edde69d18498fb2954f71a546357b07ab996aEvan Millar } 841c64edde69d18498fb2954f71a546357b07ab996aEvan Millar 842c64edde69d18498fb2954f71a546357b07ab996aEvan Millar /* arg2 on the source message has an id that needs to be retained in replies 84369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * see NsdManager for details */ 844c64edde69d18498fb2954f71a546357b07ab996aEvan Millar private Message obtainMessage(Message srcMsg) { 8458564c8da817a845353d213acd8636b76f567b234Steve Block Message msg = Message.obtain(); 846c64edde69d18498fb2954f71a546357b07ab996aEvan Millar msg.arg2 = srcMsg.arg2; 847c64edde69d18498fb2954f71a546357b07ab996aEvan Millar return msg; 84869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes } 849c64edde69d18498fb2954f71a546357b07ab996aEvan Millar 850c64edde69d18498fb2954f71a546357b07ab996aEvan Millar private void replyToMessage(Message msg, int what) { 851c64edde69d18498fb2954f71a546357b07ab996aEvan Millar if (msg.replyTo == null) return; 85269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes Message dstMsg = obtainMessage(msg); 853c64edde69d18498fb2954f71a546357b07ab996aEvan Millar dstMsg.what = what; 8548564c8da817a845353d213acd8636b76f567b234Steve Block mReplyChannel.replyToMessage(msg, dstMsg); 855c64edde69d18498fb2954f71a546357b07ab996aEvan Millar } 856c64edde69d18498fb2954f71a546357b07ab996aEvan Millar 857c64edde69d18498fb2954f71a546357b07ab996aEvan Millar private void replyToMessage(Message msg, int what, int arg1) { 85869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes if (msg.replyTo == null) return; 85969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes Message dstMsg = obtainMessage(msg); 860c64edde69d18498fb2954f71a546357b07ab996aEvan Millar dstMsg.what = what; 86169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes dstMsg.arg1 = arg1; 862c64edde69d18498fb2954f71a546357b07ab996aEvan Millar mReplyChannel.replyToMessage(msg, dstMsg); 863c64edde69d18498fb2954f71a546357b07ab996aEvan Millar } 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void replyToMessage(Message msg, int what, Object obj) { 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (msg.replyTo == null) return; 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Message dstMsg = obtainMessage(msg); 86869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes dstMsg.what = what; 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dstMsg.obj = obj; 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mReplyChannel.replyToMessage(msg, dstMsg); 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Information tracked per client */ 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class ClientInfo { 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MAX_LIMIT = 10; 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final AsyncChannel mChannel; 878c6a410164e1fd728cf7873493baacca7bc29548dMark Salyzyn private final Messenger mMessenger; 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Remembers a resolved service until getaddrinfo completes */ 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private NsdServiceInfo mResolvedService; 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* A map from client id to unique id sent to mDns */ 883906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn private SparseArray<Integer> mClientIds = new SparseArray<Integer>(); 884906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn 885906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn /* A map from client id to the type of the request we had received */ 886906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn private SparseArray<Integer> mClientRequests = new SparseArray<Integer>(); 887906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn 888906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn private ClientInfo(AsyncChannel c, Messenger m) { 889906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn mChannel = c; 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMessenger = m; 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) Slog.d(TAG, "New client, channel: " + c + " messenger: " + m); 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 89569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes public String toString() { 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuffer sb = new StringBuffer(); 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("mChannel ").append(mChannel).append("\n"); 89869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes sb.append("mMessenger ").append(mMessenger).append("\n"); 89969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes sb.append("mResolvedService ").append(mResolvedService).append("\n"); 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for(int i = 0; i< mClientIds.size(); i++) { 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int clientID = mClientIds.keyAt(i); 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append("clientId ").append(clientID). 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project append(" mDnsId ").append(mClientIds.valueAt(i)). 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project append(" type ").append(mClientRequests.get(clientID)).append("\n"); 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sb.toString(); 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 908c6a410164e1fd728cf7873493baacca7bc29548dMark Salyzyn 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Remove any pending requests from the global map when we get rid of a client, 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // and send cancellations to the daemon. 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void expungeAllRequests() { 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int globalId, clientId, i; 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (i = 0; i < mClientIds.size(); i++) { 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clientId = mClientIds.keyAt(i); 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project globalId = mClientIds.valueAt(i); 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIdToClientInfoMap.remove(globalId); 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (DBG) Slog.d(TAG, "Terminating client-ID " + clientId + 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " global-ID " + globalId + " type " + mClientRequests.get(clientId)); 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (mClientRequests.get(clientId)) { 920c6a410164e1fd728cf7873493baacca7bc29548dMark Salyzyn case NsdManager.DISCOVER_SERVICES: 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stopServiceDiscovery(globalId); 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case NsdManager.RESOLVE_SERVICE: 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stopResolveService(globalId); 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case NsdManager.REGISTER_SERVICE: 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unregisterService(globalId); 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 931f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn } 932f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn } 933f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn mClientIds.clear(); 934f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn mClientRequests.clear(); 935f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn } 936f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn 937f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn // mClientIds is a sparse array of listener id -> mDnsClient id. For a given mDnsClient id, 938f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn // return the corresponding listener id. mDnsClient id is also called a global id. 939f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn private int getClientId(final int globalId) { 940f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn // This doesn't use mClientIds.indexOfValue because indexOfValue uses == (not .equals) 941f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn // while also coercing the int primitives to Integer objects. 942f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn for (int i = 0, nSize = mClientIds.size(); i < nSize; i++) { 943f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn int mDnsId = mClientIds.valueAt(i); 944f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn if (globalId == mDnsId) { 945f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn return mClientIds.keyAt(i); 946f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn } 947f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn } 948f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn return -1; 949f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn } 950f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn } 951f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn} 952f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn