17d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff/* 27d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * Copyright (C) 2010 The Android Open Source Project 37d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * 47d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * Licensed under the Apache License, Version 2.0 (the "License"); 57d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * you may not use this file except in compliance with the License. 67d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * You may obtain a copy of the License at 77d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * 87d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * http://www.apache.org/licenses/LICENSE-2.0 97d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * 107d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * Unless required by applicable law or agreed to in writing, software 117d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * distributed under the License is distributed on an "AS IS" BASIS, 127d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * See the License for the specific language governing permissions and 147d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * limitations under the License. 157d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff */ 167d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 177d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffpackage com.android.server; 187d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 197d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport android.content.Context; 203ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriffimport android.content.ContentResolver; 213ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriffimport android.content.Intent; 227d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport android.content.pm.PackageManager; 23919aca5663be997eb238a9635e742858d29b8592Irfan Sheriffimport android.database.ContentObserver; 2422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriffimport android.net.nsd.NsdServiceInfo; 257d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport android.net.nsd.DnsSdTxtRecord; 267d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport android.net.nsd.INsdManager; 277d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport android.net.nsd.NsdManager; 287d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport android.os.Binder; 297d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport android.os.Message; 307d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport android.os.Messenger; 315ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackbornimport android.os.UserHandle; 323ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriffimport android.provider.Settings; 337d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport android.util.Slog; 3422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriffimport android.util.SparseArray; 357d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 367d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport java.io.FileDescriptor; 377d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport java.io.PrintWriter; 38b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Laneimport java.io.UnsupportedEncodingException; 39817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriffimport java.net.InetAddress; 40817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriffimport java.util.HashMap; 417d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport java.util.List; 42b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Laneimport java.util.Locale; 43b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Laneimport java.util.Map; 44817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriffimport java.util.concurrent.CountDownLatch; 457d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 467d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffimport com.android.internal.util.AsyncChannel; 473ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriffimport com.android.internal.util.Protocol; 483ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriffimport com.android.internal.util.State; 493ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriffimport com.android.internal.util.StateMachine; 50771cd657acc37b50bafe18bf5f649d3c1d85b3d8Christopher Laneimport com.android.server.NativeDaemonConnector.Command; 517d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 527d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff/** 537d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * Network Service Discovery Service handles remote service discovery operation requests by 547d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * implementing the INsdManager interface. 557d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * 567d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * @hide 577d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff */ 587d024d372431effc87168afdc7cbe387680c4935Irfan Sheriffpublic class NsdService extends INsdManager.Stub { 597d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff private static final String TAG = "NsdService"; 607d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff private static final String MDNS_TAG = "mDnsConnector"; 617d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 627d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff private static final boolean DBG = true; 637d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 647d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff private Context mContext; 653ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff private ContentResolver mContentResolver; 663ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff private NsdStateMachine mNsdStateMachine; 677d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 687d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff /** 697d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff * Clients receiving asynchronous messages 707d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff */ 71817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff private HashMap<Messenger, ClientInfo> mClients = new HashMap<Messenger, ClientInfo>(); 727d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 7322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff /* A map from unique id to client info */ 7422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private SparseArray<ClientInfo> mIdToClientInfoMap= new SparseArray<ClientInfo>(); 7522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 767d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff private AsyncChannel mReplyChannel = new AsyncChannel(); 777d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 78817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff private int INVALID_ID = 0; 79817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff private int mUniqueId = 1; 80817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff 813ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff private static final int BASE = Protocol.BASE_NSD_MANAGER; 8222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private static final int CMD_TO_STRING_COUNT = NsdManager.RESOLVE_SERVICE - BASE + 1; 833ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT]; 843ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 853ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff static { 863ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff sCmdToString[NsdManager.DISCOVER_SERVICES - BASE] = "DISCOVER"; 873ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff sCmdToString[NsdManager.STOP_DISCOVERY - BASE] = "STOP-DISCOVER"; 883ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff sCmdToString[NsdManager.REGISTER_SERVICE - BASE] = "REGISTER"; 893ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff sCmdToString[NsdManager.UNREGISTER_SERVICE - BASE] = "UNREGISTER"; 903ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff sCmdToString[NsdManager.RESOLVE_SERVICE - BASE] = "RESOLVE"; 913ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 927d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 933ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff private static String cmdToString(int cmd) { 943ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff cmd -= BASE; 953ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff if ((cmd >= 0) && (cmd < sCmdToString.length)) { 963ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff return sCmdToString[cmd]; 973ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } else { 983ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff return null; 997d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 1003ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 1013ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 1023ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff private class NsdStateMachine extends StateMachine { 1033ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 10422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private final DefaultState mDefaultState = new DefaultState(); 10522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private final DisabledState mDisabledState = new DisabledState(); 10622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private final EnabledState mEnabledState = new EnabledState(); 1077d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 1087d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff @Override 109bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville protected String getWhatToString(int what) { 110bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville return cmdToString(what); 1113ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 1123ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 113919aca5663be997eb238a9635e742858d29b8592Irfan Sheriff /** 114919aca5663be997eb238a9635e742858d29b8592Irfan Sheriff * Observes the NSD on/off setting, and takes action when changed. 115919aca5663be997eb238a9635e742858d29b8592Irfan Sheriff */ 116919aca5663be997eb238a9635e742858d29b8592Irfan Sheriff private void registerForNsdSetting() { 117919aca5663be997eb238a9635e742858d29b8592Irfan Sheriff ContentObserver contentObserver = new ContentObserver(this.getHandler()) { 118919aca5663be997eb238a9635e742858d29b8592Irfan Sheriff @Override 119919aca5663be997eb238a9635e742858d29b8592Irfan Sheriff public void onChange(boolean selfChange) { 120919aca5663be997eb238a9635e742858d29b8592Irfan Sheriff if (isNsdEnabled()) { 121919aca5663be997eb238a9635e742858d29b8592Irfan Sheriff mNsdStateMachine.sendMessage(NsdManager.ENABLE); 122919aca5663be997eb238a9635e742858d29b8592Irfan Sheriff } else { 123919aca5663be997eb238a9635e742858d29b8592Irfan Sheriff mNsdStateMachine.sendMessage(NsdManager.DISABLE); 124919aca5663be997eb238a9635e742858d29b8592Irfan Sheriff } 125919aca5663be997eb238a9635e742858d29b8592Irfan Sheriff } 126919aca5663be997eb238a9635e742858d29b8592Irfan Sheriff }; 127919aca5663be997eb238a9635e742858d29b8592Irfan Sheriff 128919aca5663be997eb238a9635e742858d29b8592Irfan Sheriff mContext.getContentResolver().registerContentObserver( 129625239a05401bbf18b04d9874cea3f82da7c29a1Jeff Sharkey Settings.Global.getUriFor(Settings.Global.NSD_ON), 130919aca5663be997eb238a9635e742858d29b8592Irfan Sheriff false, contentObserver); 131919aca5663be997eb238a9635e742858d29b8592Irfan Sheriff } 132919aca5663be997eb238a9635e742858d29b8592Irfan Sheriff 1333ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff NsdStateMachine(String name) { 1343ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff super(name); 1353ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff addState(mDefaultState); 1363ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff addState(mDisabledState, mDefaultState); 1373ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff addState(mEnabledState, mDefaultState); 1383ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff if (isNsdEnabled()) { 1393ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff setInitialState(mEnabledState); 1403ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } else { 1413ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff setInitialState(mDisabledState); 1423ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 143bbf30dfd767f823f5f40d14b498e2a593454c5c9Wink Saville setLogRecSize(25); 144919aca5663be997eb238a9635e742858d29b8592Irfan Sheriff registerForNsdSetting(); 1453ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 1463ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 1473ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff class DefaultState extends State { 1483ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff @Override 1493ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff public boolean processMessage(Message msg) { 150f31760c63401be72748487c9d4fce3fecdedede4Dave Platt ClientInfo cInfo = null; 1513ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff switch (msg.what) { 1523ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 1533ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 1543ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff AsyncChannel c = (AsyncChannel) msg.obj; 1553ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff if (DBG) Slog.d(TAG, "New client listening to asynchronous messages"); 1563ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff c.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED); 157f31760c63401be72748487c9d4fce3fecdedede4Dave Platt cInfo = new ClientInfo(c, msg.replyTo); 1583ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff mClients.put(msg.replyTo, cInfo); 1593ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } else { 1603ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff Slog.e(TAG, "Client connection failure, error=" + msg.arg1); 161817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } 162817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff break; 1633ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 164f31760c63401be72748487c9d4fce3fecdedede4Dave Platt switch (msg.arg1) { 165f31760c63401be72748487c9d4fce3fecdedede4Dave Platt case AsyncChannel.STATUS_SEND_UNSUCCESSFUL: 166f31760c63401be72748487c9d4fce3fecdedede4Dave Platt Slog.e(TAG, "Send failed, client connection lost"); 167f31760c63401be72748487c9d4fce3fecdedede4Dave Platt break; 168f31760c63401be72748487c9d4fce3fecdedede4Dave Platt case AsyncChannel.STATUS_REMOTE_DISCONNECTION: 169f31760c63401be72748487c9d4fce3fecdedede4Dave Platt if (DBG) Slog.d(TAG, "Client disconnected"); 170f31760c63401be72748487c9d4fce3fecdedede4Dave Platt break; 171f31760c63401be72748487c9d4fce3fecdedede4Dave Platt default: 172f31760c63401be72748487c9d4fce3fecdedede4Dave Platt if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1); 173f31760c63401be72748487c9d4fce3fecdedede4Dave Platt break; 174f31760c63401be72748487c9d4fce3fecdedede4Dave Platt } 175f31760c63401be72748487c9d4fce3fecdedede4Dave Platt cInfo = mClients.get(msg.replyTo); 176f31760c63401be72748487c9d4fce3fecdedede4Dave Platt if (cInfo != null) { 177f31760c63401be72748487c9d4fce3fecdedede4Dave Platt cInfo.expungeAllRequests(); 178f31760c63401be72748487c9d4fce3fecdedede4Dave Platt mClients.remove(msg.replyTo); 179f31760c63401be72748487c9d4fce3fecdedede4Dave Platt } 180f31760c63401be72748487c9d4fce3fecdedede4Dave Platt //Last client 181f31760c63401be72748487c9d4fce3fecdedede4Dave Platt if (mClients.size() == 0) { 182f31760c63401be72748487c9d4fce3fecdedede4Dave Platt stopMDnsDaemon(); 1833ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 1843ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff break; 1853ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: 1863ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff AsyncChannel ac = new AsyncChannel(); 1873ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff ac.connect(mContext, getHandler(), msg.replyTo); 1883ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff break; 1893ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff case NsdManager.DISCOVER_SERVICES: 19022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, 19122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff NsdManager.FAILURE_INTERNAL_ERROR); 1923ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff break; 1933ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff case NsdManager.STOP_DISCOVERY: 19422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, 19522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff NsdManager.FAILURE_INTERNAL_ERROR); 196817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff break; 1973ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff case NsdManager.REGISTER_SERVICE: 19822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, 19922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff NsdManager.FAILURE_INTERNAL_ERROR); 2003ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff break; 2013ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff case NsdManager.UNREGISTER_SERVICE: 20222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, 20322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff NsdManager.FAILURE_INTERNAL_ERROR); 2043ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff break; 2053ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff case NsdManager.RESOLVE_SERVICE: 20622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, 20722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff NsdManager.FAILURE_INTERNAL_ERROR); 2083ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff break; 20922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff case NsdManager.NATIVE_DAEMON_EVENT: 2103ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff default: 2113ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff Slog.e(TAG, "Unhandled " + msg); 2123ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff return NOT_HANDLED; 2133ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 2143ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff return HANDLED; 2157d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 2167d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 2173ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 2183ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff class DisabledState extends State { 2193ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff @Override 2203ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff public void enter() { 2213ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff sendNsdStateChangeBroadcast(false); 2223ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 2233ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 2243ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff @Override 2253ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff public boolean processMessage(Message msg) { 2263ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff switch (msg.what) { 2273ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff case NsdManager.ENABLE: 2283ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff transitionTo(mEnabledState); 2293ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff break; 2303ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff default: 2313ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff return NOT_HANDLED; 2323ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 2333ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff return HANDLED; 2343ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 2353ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 2363ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 2373ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff class EnabledState extends State { 2383ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff @Override 2393ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff public void enter() { 2403ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff sendNsdStateChangeBroadcast(true); 2413ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff if (mClients.size() > 0) { 2423ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff startMDnsDaemon(); 2433ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 2443ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 2453ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 2463ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff @Override 2473ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff public void exit() { 2483ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff if (mClients.size() > 0) { 2493ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff stopMDnsDaemon(); 2503ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 2513ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 2523ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 25322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private boolean requestLimitReached(ClientInfo clientInfo) { 25422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (clientInfo.mClientIds.size() >= ClientInfo.MAX_LIMIT) { 25522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (DBG) Slog.d(TAG, "Exceeded max outstanding requests " + clientInfo); 25622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff return true; 25722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 25822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff return false; 25922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 26022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 261f31760c63401be72748487c9d4fce3fecdedede4Dave Platt private void storeRequestMap(int clientId, int globalId, ClientInfo clientInfo, int what) { 26222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff clientInfo.mClientIds.put(clientId, globalId); 263f31760c63401be72748487c9d4fce3fecdedede4Dave Platt clientInfo.mClientRequests.put(clientId, what); 26422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff mIdToClientInfoMap.put(globalId, clientInfo); 26522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 26622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 26722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) { 26822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff clientInfo.mClientIds.remove(clientId); 269f31760c63401be72748487c9d4fce3fecdedede4Dave Platt clientInfo.mClientRequests.remove(clientId); 27022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff mIdToClientInfoMap.remove(globalId); 27122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 27222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 2733ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff @Override 2743ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff public boolean processMessage(Message msg) { 2753ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff ClientInfo clientInfo; 27622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff NsdServiceInfo servInfo; 2773ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff boolean result = HANDLED; 27822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff int id; 2793ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff switch (msg.what) { 2803ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 2813ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff //First client 2823ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL && 2833ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff mClients.size() == 0) { 2843ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff startMDnsDaemon(); 2853ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 2863ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff result = NOT_HANDLED; 2873ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff break; 2883ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 2893ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff result = NOT_HANDLED; 2903ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff break; 2913ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff case NsdManager.DISABLE: 2923ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff //TODO: cleanup clients 2933ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff transitionTo(mDisabledState); 2943ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff break; 2953ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff case NsdManager.DISCOVER_SERVICES: 2963ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff if (DBG) Slog.d(TAG, "Discover services"); 29722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff servInfo = (NsdServiceInfo) msg.obj; 2983ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff clientInfo = mClients.get(msg.replyTo); 29922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 30022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (requestLimitReached(clientInfo)) { 30122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, 30222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff NsdManager.FAILURE_MAX_LIMIT); 3033ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff break; 3043ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 30522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 30622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff id = getUniqueId(); 30722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (discoverServices(id, servInfo.getServiceType())) { 30822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (DBG) { 30922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff Slog.d(TAG, "Discover " + msg.arg2 + " " + id + 31022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff servInfo.getServiceType()); 31122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 312f31760c63401be72748487c9d4fce3fecdedede4Dave Platt storeRequestMap(msg.arg2, id, clientInfo, msg.what); 31322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff replyToMessage(msg, NsdManager.DISCOVER_SERVICES_STARTED, servInfo); 3143ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } else { 31522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff stopServiceDiscovery(id); 31622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, 31722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff NsdManager.FAILURE_INTERNAL_ERROR); 3183ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 3193ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff break; 3203ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff case NsdManager.STOP_DISCOVERY: 3213ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff if (DBG) Slog.d(TAG, "Stop service discovery"); 3223ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff clientInfo = mClients.get(msg.replyTo); 32322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 32422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff try { 32522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff id = clientInfo.mClientIds.get(msg.arg2).intValue(); 32622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } catch (NullPointerException e) { 32722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, 32822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff NsdManager.FAILURE_INTERNAL_ERROR); 3293ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff break; 3303ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 33122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff removeRequestMap(msg.arg2, id, clientInfo); 33222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (stopServiceDiscovery(id)) { 33322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff replyToMessage(msg, NsdManager.STOP_DISCOVERY_SUCCEEDED); 3343ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } else { 33522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, 33622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff NsdManager.FAILURE_INTERNAL_ERROR); 3373ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 3383ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff break; 3393ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff case NsdManager.REGISTER_SERVICE: 3403ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff if (DBG) Slog.d(TAG, "Register service"); 3413ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff clientInfo = mClients.get(msg.replyTo); 34222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (requestLimitReached(clientInfo)) { 34322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, 34422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff NsdManager.FAILURE_MAX_LIMIT); 34522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff break; 3463ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 3473ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 34822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff id = getUniqueId(); 34922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (registerService(id, (NsdServiceInfo) msg.obj)) { 35022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (DBG) Slog.d(TAG, "Register " + msg.arg2 + " " + id); 351f31760c63401be72748487c9d4fce3fecdedede4Dave Platt storeRequestMap(msg.arg2, id, clientInfo, msg.what); 35222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff // Return success after mDns reports success 3533ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } else { 35422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff unregisterService(id); 35522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, 35622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff NsdManager.FAILURE_INTERNAL_ERROR); 3573ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 3583ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff break; 3593ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff case NsdManager.UNREGISTER_SERVICE: 3603ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff if (DBG) Slog.d(TAG, "unregister service"); 3613ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff clientInfo = mClients.get(msg.replyTo); 36222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff try { 36322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff id = clientInfo.mClientIds.get(msg.arg2).intValue(); 36422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } catch (NullPointerException e) { 36522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, 36622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff NsdManager.FAILURE_INTERNAL_ERROR); 36722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff break; 36822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 36922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff removeRequestMap(msg.arg2, id, clientInfo); 37022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (unregisterService(id)) { 37122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_SUCCEEDED); 3723ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } else { 37322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, 37422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff NsdManager.FAILURE_INTERNAL_ERROR); 3753ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 3763ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff break; 3773ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff case NsdManager.RESOLVE_SERVICE: 3783ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff if (DBG) Slog.d(TAG, "Resolve service"); 37922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff servInfo = (NsdServiceInfo) msg.obj; 3803ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff clientInfo = mClients.get(msg.replyTo); 3813ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 38222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 38322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (clientInfo.mResolvedService != null) { 38422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, 38522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff NsdManager.FAILURE_ALREADY_ACTIVE); 3863ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff break; 3873ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 38822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 38922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff id = getUniqueId(); 39022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (resolveService(id, servInfo)) { 39122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff clientInfo.mResolvedService = new NsdServiceInfo(); 392f31760c63401be72748487c9d4fce3fecdedede4Dave Platt storeRequestMap(msg.arg2, id, clientInfo, msg.what); 3933ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } else { 39422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, 39522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff NsdManager.FAILURE_INTERNAL_ERROR); 3963ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 3973ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff break; 39822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff case NsdManager.NATIVE_DAEMON_EVENT: 39922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff NativeEvent event = (NativeEvent) msg.obj; 400ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran if (!handleNativeEvent(event.code, event.raw, event.cooked)) { 4016727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan result = NOT_HANDLED; 4026727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan } 40322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff break; 4043ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff default: 4053ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff result = NOT_HANDLED; 4063ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff break; 4073ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 4083ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff return result; 4093ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 4106727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan 4116727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan private boolean handleNativeEvent(int code, String raw, String[] cooked) { 4126727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan boolean handled = true; 4136727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan NsdServiceInfo servInfo; 4146727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan int id = Integer.parseInt(cooked[1]); 4156727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan ClientInfo clientInfo = mIdToClientInfoMap.get(id); 4166727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan if (clientInfo == null) { 4176727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan Slog.e(TAG, "Unique id with no client mapping: " + id); 4186727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan handled = false; 4196727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan return handled; 4206727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan } 4216727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan 4226727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan /* This goes in response as msg.arg2 */ 4235a577903d366ff07b3c4ec6359e4757154f49790Christopher Lane int clientId = clientInfo.getClientId(id); 4245a577903d366ff07b3c4ec6359e4757154f49790Christopher Lane if (clientId < 0) { 4258ed09e893f6a4b6a4f6503186515b8f6978baa14Vinit Deshapnde // This can happen because of race conditions. For example, 4268ed09e893f6a4b6a4f6503186515b8f6978baa14Vinit Deshapnde // SERVICE_FOUND may race with STOP_SERVICE_DISCOVERY, 4278ed09e893f6a4b6a4f6503186515b8f6978baa14Vinit Deshapnde // and we may get in this situation. 4288ed09e893f6a4b6a4f6503186515b8f6978baa14Vinit Deshapnde Slog.d(TAG, "Notification for a listener that is no longer active: " + id); 4298ed09e893f6a4b6a4f6503186515b8f6978baa14Vinit Deshapnde handled = false; 4308ed09e893f6a4b6a4f6503186515b8f6978baa14Vinit Deshapnde return handled; 4316727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan } 4328ed09e893f6a4b6a4f6503186515b8f6978baa14Vinit Deshapnde 4336727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan switch (code) { 4346727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan case NativeResponseCode.SERVICE_FOUND: 4356727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan /* NNN uniqueId serviceName regType domain */ 4366727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan if (DBG) Slog.d(TAG, "SERVICE_FOUND Raw: " + raw); 437b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane servInfo = new NsdServiceInfo(cooked[2], cooked[3]); 4386727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan clientInfo.mChannel.sendMessage(NsdManager.SERVICE_FOUND, 0, 4396727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan clientId, servInfo); 4406727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan break; 4416727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan case NativeResponseCode.SERVICE_LOST: 4426727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan /* NNN uniqueId serviceName regType domain */ 4436727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan if (DBG) Slog.d(TAG, "SERVICE_LOST Raw: " + raw); 444b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane servInfo = new NsdServiceInfo(cooked[2], cooked[3]); 4456727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan clientInfo.mChannel.sendMessage(NsdManager.SERVICE_LOST, 0, 4466727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan clientId, servInfo); 4476727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan break; 4486727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan case NativeResponseCode.SERVICE_DISCOVERY_FAILED: 4496727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan /* NNN uniqueId errorCode */ 4506727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan if (DBG) Slog.d(TAG, "SERVICE_DISC_FAILED Raw: " + raw); 4516727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan clientInfo.mChannel.sendMessage(NsdManager.DISCOVER_SERVICES_FAILED, 4526727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan NsdManager.FAILURE_INTERNAL_ERROR, clientId); 4536727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan break; 4546727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan case NativeResponseCode.SERVICE_REGISTERED: 4556727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan /* NNN regId serviceName regType */ 4566727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan if (DBG) Slog.d(TAG, "SERVICE_REGISTERED Raw: " + raw); 457b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane servInfo = new NsdServiceInfo(cooked[2], null); 4586727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_SUCCEEDED, 4596727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan id, clientId, servInfo); 4606727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan break; 4616727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan case NativeResponseCode.SERVICE_REGISTRATION_FAILED: 4626727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan /* NNN regId errorCode */ 4636727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan if (DBG) Slog.d(TAG, "SERVICE_REGISTER_FAILED Raw: " + raw); 4646727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_FAILED, 4656727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan NsdManager.FAILURE_INTERNAL_ERROR, clientId); 4666727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan break; 4676727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan case NativeResponseCode.SERVICE_UPDATED: 4686727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan /* NNN regId */ 4696727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan break; 4706727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan case NativeResponseCode.SERVICE_UPDATE_FAILED: 4716727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan /* NNN regId errorCode */ 4726727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan break; 4736727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan case NativeResponseCode.SERVICE_RESOLVED: 4746727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan /* NNN resolveId fullName hostName port txtlen txtdata */ 4756727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan if (DBG) Slog.d(TAG, "SERVICE_RESOLVED Raw: " + raw); 476ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran int index = 0; 477ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran while (index < cooked[2].length() && cooked[2].charAt(index) != '.') { 478ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran if (cooked[2].charAt(index) == '\\') { 479ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran ++index; 480ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran } 481ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran ++index; 482ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran } 483ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran if (index >= cooked[2].length()) { 4846727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan Slog.e(TAG, "Invalid service found " + raw); 4856727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan break; 4866727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan } 4876727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan String name = cooked[2].substring(0, index); 4886727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan String rest = cooked[2].substring(index); 4896727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan String type = rest.replace(".local.", ""); 4906727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan 491ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran name = unescape(name); 492ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran 4936727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan clientInfo.mResolvedService.setServiceName(name); 4946727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan clientInfo.mResolvedService.setServiceType(type); 4956727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4])); 4966727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan 4976727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan stopResolveService(id); 4984038724a536c990859866489195add7ed537006bVinit Deshapnde removeRequestMap(clientId, id, clientInfo); 4994038724a536c990859866489195add7ed537006bVinit Deshapnde 5004038724a536c990859866489195add7ed537006bVinit Deshapnde int id2 = getUniqueId(); 5014038724a536c990859866489195add7ed537006bVinit Deshapnde if (getAddrInfo(id2, cooked[3])) { 502f31760c63401be72748487c9d4fce3fecdedede4Dave Platt storeRequestMap(clientId, id2, clientInfo, NsdManager.RESOLVE_SERVICE); 5034038724a536c990859866489195add7ed537006bVinit Deshapnde } else { 5046727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, 5056727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan NsdManager.FAILURE_INTERNAL_ERROR, clientId); 5066727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan clientInfo.mResolvedService = null; 5076727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan } 5086727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan break; 5096727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan case NativeResponseCode.SERVICE_RESOLUTION_FAILED: 5106727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan /* NNN resolveId errorCode */ 5116727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan if (DBG) Slog.d(TAG, "SERVICE_RESOLVE_FAILED Raw: " + raw); 5126727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan stopResolveService(id); 5136727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan removeRequestMap(clientId, id, clientInfo); 5146727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan clientInfo.mResolvedService = null; 5156727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, 5166727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan NsdManager.FAILURE_INTERNAL_ERROR, clientId); 5176727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan break; 5186727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan case NativeResponseCode.SERVICE_GET_ADDR_FAILED: 5196727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan /* NNN resolveId errorCode */ 5206727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan stopGetAddrInfo(id); 5216727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan removeRequestMap(clientId, id, clientInfo); 5226727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan clientInfo.mResolvedService = null; 5236727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan if (DBG) Slog.d(TAG, "SERVICE_RESOLVE_FAILED Raw: " + raw); 5246727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, 5256727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan NsdManager.FAILURE_INTERNAL_ERROR, clientId); 5266727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan break; 5276727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS: 5286727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan /* NNN resolveId hostname ttl addr */ 5296727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan if (DBG) Slog.d(TAG, "SERVICE_GET_ADDR_SUCCESS Raw: " + raw); 5306727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan try { 5316727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan clientInfo.mResolvedService.setHost(InetAddress.getByName(cooked[4])); 5326727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_SUCCEEDED, 5336727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan 0, clientId, clientInfo.mResolvedService); 5346727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan } catch (java.net.UnknownHostException e) { 5356727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, 5366727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan NsdManager.FAILURE_INTERNAL_ERROR, clientId); 5376727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan } 5386727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan stopGetAddrInfo(id); 5396727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan removeRequestMap(clientId, id, clientInfo); 5406727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan clientInfo.mResolvedService = null; 5416727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan break; 5426727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan default: 5436727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan handled = false; 5446727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan break; 5456727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan } 5466727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan return handled; 5476727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan } 5483ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 5497d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 5507d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 551ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran private String unescape(String s) { 552ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran StringBuilder sb = new StringBuilder(s.length()); 553ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran for (int i = 0; i < s.length(); ++i) { 554ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran char c = s.charAt(i); 555ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran if (c == '\\') { 556ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran if (++i >= s.length()) { 557ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran Slog.e(TAG, "Unexpected end of escape sequence in: " + s); 558ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran break; 559ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran } 560ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran c = s.charAt(i); 561ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran if (c != '.' && c != '\\') { 562ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran if (i + 2 >= s.length()) { 563ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran Slog.e(TAG, "Unexpected end of escape sequence in: " + s); 564ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran break; 565ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran } 566ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran c = (char) ((c-'0') * 100 + (s.charAt(i+1)-'0') * 10 + (s.charAt(i+2)-'0')); 567ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran i += 2; 568ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran } 569ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran } 570ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran sb.append(c); 571ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran } 572ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran return sb.toString(); 573ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran } 574ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran 5757d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff private NativeDaemonConnector mNativeConnector; 5767d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff private final CountDownLatch mNativeDaemonConnected = new CountDownLatch(1); 5777d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 5787d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff private NsdService(Context context) { 5797d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff mContext = context; 5803ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff mContentResolver = context.getContentResolver(); 5817d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 5827d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff mNativeConnector = new NativeDaemonConnector(new NativeCallbackReceiver(), "mdns", 10, 58377b987f1a1bb6028a871de01065b94c4cfff0b5cDianne Hackborn MDNS_TAG, 25, null); 5843ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 5853ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff mNsdStateMachine = new NsdStateMachine(TAG); 5863ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff mNsdStateMachine.start(); 5873ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 5887d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff Thread th = new Thread(mNativeConnector, MDNS_TAG); 5897d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff th.start(); 5907d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 5917d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 5927d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff public static NsdService create(Context context) throws InterruptedException { 5937d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff NsdService service = new NsdService(context); 5943ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff service.mNativeDaemonConnected.await(); 5957d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff return service; 5967d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 5977d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 5987d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff public Messenger getMessenger() { 59992784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET, 60092784670c48759c0db604ddb95c05a7b9bdebed8Irfan Sheriff "NsdService"); 6013ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff return new Messenger(mNsdStateMachine.getHandler()); 6023ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 6033ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 6043ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff public void setEnabled(boolean enable) { 6053ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL, 6063ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff "NsdService"); 607625239a05401bbf18b04d9874cea3f82da7c29a1Jeff Sharkey Settings.Global.putInt(mContentResolver, Settings.Global.NSD_ON, enable ? 1 : 0); 6083ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff if (enable) { 6093ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff mNsdStateMachine.sendMessage(NsdManager.ENABLE); 6103ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } else { 6113ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff mNsdStateMachine.sendMessage(NsdManager.DISABLE); 6123ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 6133ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 6143ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 6153ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff private void sendNsdStateChangeBroadcast(boolean enabled) { 61654ac7a510245e5f00c16ff5595b6ae8d002c1c3bIrfan Sheriff final Intent intent = new Intent(NsdManager.ACTION_NSD_STATE_CHANGED); 6173ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 6183ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff if (enabled) { 6193ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff intent.putExtra(NsdManager.EXTRA_NSD_STATE, NsdManager.NSD_STATE_ENABLED); 6203ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } else { 6213ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff intent.putExtra(NsdManager.EXTRA_NSD_STATE, NsdManager.NSD_STATE_DISABLED); 6223ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 6235ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 6243ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 6253ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 6263ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff private boolean isNsdEnabled() { 627625239a05401bbf18b04d9874cea3f82da7c29a1Jeff Sharkey boolean ret = Settings.Global.getInt(mContentResolver, Settings.Global.NSD_ON, 1) == 1; 6283ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff if (DBG) Slog.d(TAG, "Network service discovery enabled " + ret); 6293ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff return ret; 6307d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 6317d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 632817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff private int getUniqueId() { 633817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff if (++mUniqueId == INVALID_ID) return ++mUniqueId; 634817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return mUniqueId; 635817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } 636817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff 63703666c705ddabe0e7c5869ab69c2ca8b964164e9Sreeram Ramachandran /* These should be in sync with system/netd/server/ResponseCode.h */ 6387d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff class NativeResponseCode { 639817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff public static final int SERVICE_DISCOVERY_FAILED = 602; 640817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff public static final int SERVICE_FOUND = 603; 641817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff public static final int SERVICE_LOST = 604; 6427d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 643817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff public static final int SERVICE_REGISTRATION_FAILED = 605; 644817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff public static final int SERVICE_REGISTERED = 606; 6457d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 646817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff public static final int SERVICE_RESOLUTION_FAILED = 607; 647817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff public static final int SERVICE_RESOLVED = 608; 6487d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 649817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff public static final int SERVICE_UPDATED = 609; 650817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff public static final int SERVICE_UPDATE_FAILED = 610; 6517d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 652817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff public static final int SERVICE_GET_ADDR_FAILED = 611; 653817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff public static final int SERVICE_GET_ADDR_SUCCESS = 612; 654817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } 6557d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 65622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private class NativeEvent { 6576727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan final int code; 6586727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan final String raw; 659ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran final String[] cooked; 66022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 661ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran NativeEvent(int code, String raw, String[] cooked) { 66222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff this.code = code; 66322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff this.raw = raw; 664ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran this.cooked = cooked; 66522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 66622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 66722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 6687d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff class NativeCallbackReceiver implements INativeDaemonConnectorCallbacks { 6697d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff public void onDaemonConnected() { 6707d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff mNativeDaemonConnected.countDown(); 6717d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 6727d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 67377b987f1a1bb6028a871de01065b94c4cfff0b5cDianne Hackborn public boolean onCheckHoldWakeLock(int code) { 67477b987f1a1bb6028a871de01065b94c4cfff0b5cDianne Hackborn return false; 67577b987f1a1bb6028a871de01065b94c4cfff0b5cDianne Hackborn } 67677b987f1a1bb6028a871de01065b94c4cfff0b5cDianne Hackborn 6777d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff public boolean onEvent(int code, String raw, String[] cooked) { 67822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff // TODO: NDC translates a message to a callback, we could enhance NDC to 67922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff // directly interact with a state machine through messages 680ef12884da7c8844f8dd27cbc9c9980f685b73a2cSreeram Ramachandran NativeEvent event = new NativeEvent(code, raw, cooked); 68122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff mNsdStateMachine.sendMessage(NsdManager.NATIVE_DAEMON_EVENT, event); 68222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff return true; 68322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 68422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 685817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff 686817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff private boolean startMDnsDaemon() { 687817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff if (DBG) Slog.d(TAG, "startMDnsDaemon"); 688817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff try { 689817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff mNativeConnector.execute("mdnssd", "start-service"); 690817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } catch(NativeDaemonConnectorException e) { 691817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff Slog.e(TAG, "Failed to start daemon" + e); 692817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return false; 693817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } 694817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return true; 695817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } 696817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff 697817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff private boolean stopMDnsDaemon() { 698817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff if (DBG) Slog.d(TAG, "stopMDnsDaemon"); 699817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff try { 700817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff mNativeConnector.execute("mdnssd", "stop-service"); 701817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } catch(NativeDaemonConnectorException e) { 702817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff Slog.e(TAG, "Failed to start daemon" + e); 703817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return false; 704817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } 705817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return true; 706817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } 707817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff 70822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private boolean registerService(int regId, NsdServiceInfo service) { 709817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff if (DBG) Slog.d(TAG, "registerService: " + regId + " " + service); 7107d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff try { 711b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane Command cmd = new Command("mdnssd", "register", regId, service.getServiceName(), 7127d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff service.getServiceType(), service.getPort()); 713b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane 714b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane // Add TXT records as additional arguments. 715b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane Map<String, byte[]> txtRecords = service.getAttributes(); 716b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane for (String key : txtRecords.keySet()) { 717b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane try { 718b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane // TODO: Send encoded TXT record as bytes once NDC/netd supports binary data. 7190f35cdd862fba23e9bcc5344403426ae74fec55cChristopher Lane byte[] recordValue = txtRecords.get(key); 720b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane cmd.appendArg(String.format(Locale.US, "%s=%s", key, 7210f35cdd862fba23e9bcc5344403426ae74fec55cChristopher Lane recordValue != null ? new String(recordValue, "UTF_8") : "")); 722b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane } catch (UnsupportedEncodingException e) { 723b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane Slog.e(TAG, "Failed to encode txtRecord " + e); 724b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane } 725b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane } 726b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane 727b72d8b4091ab31948c91b0382a9b46afdc7ef7daChristopher Lane mNativeConnector.execute(cmd); 7287d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } catch(NativeDaemonConnectorException e) { 729817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff Slog.e(TAG, "Failed to execute registerService " + e); 730817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return false; 731817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } 732817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return true; 733817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } 734817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff 735817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff private boolean unregisterService(int regId) { 736817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff if (DBG) Slog.d(TAG, "unregisterService: " + regId); 737817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff try { 738817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff mNativeConnector.execute("mdnssd", "stop-register", regId); 739817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } catch(NativeDaemonConnectorException e) { 740817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff Slog.e(TAG, "Failed to execute unregisterService " + e); 741817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return false; 7427d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 743817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return true; 7447d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 7457d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 746817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff private boolean updateService(int regId, DnsSdTxtRecord t) { 747817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff if (DBG) Slog.d(TAG, "updateService: " + regId + " " + t); 7487d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff try { 749817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff if (t == null) return false; 7507d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff mNativeConnector.execute("mdnssd", "update", regId, t.size(), t.getRawData()); 7517d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } catch(NativeDaemonConnectorException e) { 752817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff Slog.e(TAG, "Failed to updateServices " + e); 753817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return false; 7547d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 755817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return true; 7567d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 7577d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 758817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff private boolean discoverServices(int discoveryId, String serviceType) { 759817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff if (DBG) Slog.d(TAG, "discoverServices: " + discoveryId + " " + serviceType); 7607d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff try { 7617d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff mNativeConnector.execute("mdnssd", "discover", discoveryId, serviceType); 7627d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } catch(NativeDaemonConnectorException e) { 763817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff Slog.e(TAG, "Failed to discoverServices " + e); 764817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return false; 765817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } 766817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return true; 767817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } 768817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff 769817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff private boolean stopServiceDiscovery(int discoveryId) { 770817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff if (DBG) Slog.d(TAG, "stopServiceDiscovery: " + discoveryId); 771817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff try { 772817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff mNativeConnector.execute("mdnssd", "stop-discover", discoveryId); 773817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } catch(NativeDaemonConnectorException e) { 774817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff Slog.e(TAG, "Failed to stopServiceDiscovery " + e); 775817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return false; 776817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } 777817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return true; 778817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } 779817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff 78022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private boolean resolveService(int resolveId, NsdServiceInfo service) { 781817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff if (DBG) Slog.d(TAG, "resolveService: " + resolveId + " " + service); 782817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff try { 783817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff mNativeConnector.execute("mdnssd", "resolve", resolveId, service.getServiceName(), 784817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff service.getServiceType(), "local."); 785817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } catch(NativeDaemonConnectorException e) { 786817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff Slog.e(TAG, "Failed to resolveService " + e); 787817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return false; 788817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } 789817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return true; 790817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } 791817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff 792817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff private boolean stopResolveService(int resolveId) { 793817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff if (DBG) Slog.d(TAG, "stopResolveService: " + resolveId); 794817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff try { 795817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff mNativeConnector.execute("mdnssd", "stop-resolve", resolveId); 796817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } catch(NativeDaemonConnectorException e) { 797817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff Slog.e(TAG, "Failed to stop resolve " + e); 798817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return false; 7997d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 800817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return true; 8017d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 8027d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 803817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff private boolean getAddrInfo(int resolveId, String hostname) { 804817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff if (DBG) Slog.d(TAG, "getAdddrInfo: " + resolveId); 8057d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff try { 806817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff mNativeConnector.execute("mdnssd", "getaddrinfo", resolveId, hostname); 8077d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } catch(NativeDaemonConnectorException e) { 808817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff Slog.e(TAG, "Failed to getAddrInfo " + e); 809817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return false; 8107d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 811817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return true; 8127d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 8137d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 814817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff private boolean stopGetAddrInfo(int resolveId) { 815817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff if (DBG) Slog.d(TAG, "stopGetAdddrInfo: " + resolveId); 8167d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff try { 817817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff mNativeConnector.execute("mdnssd", "stop-getaddrinfo", resolveId); 8187d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } catch(NativeDaemonConnectorException e) { 819817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff Slog.e(TAG, "Failed to stopGetAddrInfo " + e); 820817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return false; 8217d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 822817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff return true; 8237d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 8247d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 8257d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff @Override 8263ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 8277d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 8287d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff != PackageManager.PERMISSION_GRANTED) { 8297d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff pw.println("Permission Denial: can't dump ServiceDiscoverService from from pid=" 8307d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff + Binder.getCallingPid() 8317d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff + ", uid=" + Binder.getCallingUid()); 8327d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff return; 8337d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 8347d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff 8353ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff for (ClientInfo client : mClients.values()) { 8363ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff pw.println("Client Info"); 8373ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff pw.println(client); 8383ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 8393ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 8403ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff mNsdStateMachine.dump(fd, pw, args); 8417d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff } 842817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff 84322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff /* arg2 on the source message has an id that needs to be retained in replies 84422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff * see NsdManager for details */ 84522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private Message obtainMessage(Message srcMsg) { 84622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff Message msg = Message.obtain(); 84722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff msg.arg2 = srcMsg.arg2; 84822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff return msg; 849817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } 850817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff 85122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private void replyToMessage(Message msg, int what) { 85222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (msg.replyTo == null) return; 85322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff Message dstMsg = obtainMessage(msg); 85422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff dstMsg.what = what; 85522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff mReplyChannel.replyToMessage(msg, dstMsg); 856817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } 857817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff 85822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private void replyToMessage(Message msg, int what, int arg1) { 85922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (msg.replyTo == null) return; 86022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff Message dstMsg = obtainMessage(msg); 86122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff dstMsg.what = what; 86222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff dstMsg.arg1 = arg1; 86322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff mReplyChannel.replyToMessage(msg, dstMsg); 86422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff } 86522af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 86622af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private void replyToMessage(Message msg, int what, Object obj) { 86722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff if (msg.replyTo == null) return; 86822af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff Message dstMsg = obtainMessage(msg); 86922af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff dstMsg.what = what; 87022af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff dstMsg.obj = obj; 87122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff mReplyChannel.replyToMessage(msg, dstMsg); 872817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } 873817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff 874817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff /* Information tracked per client */ 875817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff private class ClientInfo { 876817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff 87722af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private static final int MAX_LIMIT = 10; 8786727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan private final AsyncChannel mChannel; 8796727e7351e2a95d64017340c51c35239210f1381Vairavan Srinivasan private final Messenger mMessenger; 880817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff /* Remembers a resolved service until getaddrinfo completes */ 88122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private NsdServiceInfo mResolvedService; 88222af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff 88322af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff /* A map from client id to unique id sent to mDns */ 88422af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff private SparseArray<Integer> mClientIds = new SparseArray<Integer>(); 885817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff 886f31760c63401be72748487c9d4fce3fecdedede4Dave Platt /* A map from client id to the type of the request we had received */ 887f31760c63401be72748487c9d4fce3fecdedede4Dave Platt private SparseArray<Integer> mClientRequests = new SparseArray<Integer>(); 888f31760c63401be72748487c9d4fce3fecdedede4Dave Platt 889817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff private ClientInfo(AsyncChannel c, Messenger m) { 890817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff mChannel = c; 891817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff mMessenger = m; 892817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff if (DBG) Slog.d(TAG, "New client, channel: " + c + " messenger: " + m); 893817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } 8943ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff 8953ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff @Override 8963ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff public String toString() { 8973ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff StringBuffer sb = new StringBuffer(); 8983ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff sb.append("mChannel ").append(mChannel).append("\n"); 8993ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff sb.append("mMessenger ").append(mMessenger).append("\n"); 9003ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff sb.append("mResolvedService ").append(mResolvedService).append("\n"); 90122af38c5261d2c03796b496e6edb125327cace16Irfan Sheriff for(int i = 0; i< mClientIds.size(); i++) { 902f31760c63401be72748487c9d4fce3fecdedede4Dave Platt int clientID = mClientIds.keyAt(i); 903f31760c63401be72748487c9d4fce3fecdedede4Dave Platt sb.append("clientId ").append(clientID). 904f31760c63401be72748487c9d4fce3fecdedede4Dave Platt append(" mDnsId ").append(mClientIds.valueAt(i)). 905f31760c63401be72748487c9d4fce3fecdedede4Dave Platt append(" type ").append(mClientRequests.get(clientID)).append("\n"); 9063ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 9073ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff return sb.toString(); 9083ef889bf561e59561ff2c6c4b2ffb586b9c5af5cIrfan Sheriff } 909f31760c63401be72748487c9d4fce3fecdedede4Dave Platt 910f31760c63401be72748487c9d4fce3fecdedede4Dave Platt // Remove any pending requests from the global map when we get rid of a client, 911f31760c63401be72748487c9d4fce3fecdedede4Dave Platt // and send cancellations to the daemon. 912f31760c63401be72748487c9d4fce3fecdedede4Dave Platt private void expungeAllRequests() { 913f31760c63401be72748487c9d4fce3fecdedede4Dave Platt int globalId, clientId, i; 914f31760c63401be72748487c9d4fce3fecdedede4Dave Platt for (i = 0; i < mClientIds.size(); i++) { 915f31760c63401be72748487c9d4fce3fecdedede4Dave Platt clientId = mClientIds.keyAt(i); 916f31760c63401be72748487c9d4fce3fecdedede4Dave Platt globalId = mClientIds.valueAt(i); 917f31760c63401be72748487c9d4fce3fecdedede4Dave Platt mIdToClientInfoMap.remove(globalId); 918f31760c63401be72748487c9d4fce3fecdedede4Dave Platt if (DBG) Slog.d(TAG, "Terminating client-ID " + clientId + 919f31760c63401be72748487c9d4fce3fecdedede4Dave Platt " global-ID " + globalId + " type " + mClientRequests.get(clientId)); 920f31760c63401be72748487c9d4fce3fecdedede4Dave Platt switch (mClientRequests.get(clientId)) { 921f31760c63401be72748487c9d4fce3fecdedede4Dave Platt case NsdManager.DISCOVER_SERVICES: 922f31760c63401be72748487c9d4fce3fecdedede4Dave Platt stopServiceDiscovery(globalId); 923f31760c63401be72748487c9d4fce3fecdedede4Dave Platt break; 924f31760c63401be72748487c9d4fce3fecdedede4Dave Platt case NsdManager.RESOLVE_SERVICE: 925f31760c63401be72748487c9d4fce3fecdedede4Dave Platt stopResolveService(globalId); 926f31760c63401be72748487c9d4fce3fecdedede4Dave Platt break; 927f31760c63401be72748487c9d4fce3fecdedede4Dave Platt case NsdManager.REGISTER_SERVICE: 928f31760c63401be72748487c9d4fce3fecdedede4Dave Platt unregisterService(globalId); 929f31760c63401be72748487c9d4fce3fecdedede4Dave Platt break; 930f31760c63401be72748487c9d4fce3fecdedede4Dave Platt default: 931f31760c63401be72748487c9d4fce3fecdedede4Dave Platt break; 932f31760c63401be72748487c9d4fce3fecdedede4Dave Platt } 933f31760c63401be72748487c9d4fce3fecdedede4Dave Platt } 934f31760c63401be72748487c9d4fce3fecdedede4Dave Platt mClientIds.clear(); 935f31760c63401be72748487c9d4fce3fecdedede4Dave Platt mClientRequests.clear(); 936f31760c63401be72748487c9d4fce3fecdedede4Dave Platt } 937f31760c63401be72748487c9d4fce3fecdedede4Dave Platt 9385a577903d366ff07b3c4ec6359e4757154f49790Christopher Lane // mClientIds is a sparse array of listener id -> mDnsClient id. For a given mDnsClient id, 9395a577903d366ff07b3c4ec6359e4757154f49790Christopher Lane // return the corresponding listener id. mDnsClient id is also called a global id. 9405a577903d366ff07b3c4ec6359e4757154f49790Christopher Lane private int getClientId(final int globalId) { 9415a577903d366ff07b3c4ec6359e4757154f49790Christopher Lane // This doesn't use mClientIds.indexOfValue because indexOfValue uses == (not .equals) 9425a577903d366ff07b3c4ec6359e4757154f49790Christopher Lane // while also coercing the int primitives to Integer objects. 9435a577903d366ff07b3c4ec6359e4757154f49790Christopher Lane for (int i = 0, nSize = mClientIds.size(); i < nSize; i++) { 9445a577903d366ff07b3c4ec6359e4757154f49790Christopher Lane int mDnsId = mClientIds.valueAt(i); 9455a577903d366ff07b3c4ec6359e4757154f49790Christopher Lane if (globalId == mDnsId) { 9465a577903d366ff07b3c4ec6359e4757154f49790Christopher Lane return mClientIds.keyAt(i); 9475a577903d366ff07b3c4ec6359e4757154f49790Christopher Lane } 9485a577903d366ff07b3c4ec6359e4757154f49790Christopher Lane } 9495a577903d366ff07b3c4ec6359e4757154f49790Christopher Lane return -1; 9505a577903d366ff07b3c4ec6359e4757154f49790Christopher Lane } 951817388e056a5d1d0e7cd7de2c6b0c9c80617bc5fIrfan Sheriff } 9527d024d372431effc87168afdc7cbe387680c4935Irfan Sheriff} 953