Loading core/java/android/net/nsd/INsdManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -26,4 +26,5 @@ import android.os.Messenger; interface INsdManager { Messenger getMessenger(); void setEnabled(boolean enable); } core/java/android/net/nsd/NsdManager.java +55 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.net.nsd; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.content.Context; import android.os.Binder; import android.os.IBinder; Loading Loading @@ -133,6 +135,44 @@ public class NsdManager { private static final String TAG = "NsdManager"; INsdManager mService; /** * Broadcast intent action to indicate whether network service discovery is * enabled or disabled. An extra {@link #EXTRA_NSD_STATE} provides the state * information as int. * * @see #EXTRA_NSD_STATE * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String NSD_STATE_CHANGED_ACTION = "android.net.nsd.STATE_CHANGED"; /** * The lookup key for an int that indicates whether network service discovery is enabled * or disabled. Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}. * * @see #NSD_STATE_DISABLED * @see #NSD_STATE_ENABLED * @hide */ public static final String EXTRA_NSD_STATE = "nsd_state"; /** * Network service discovery is disabled * * @see #NSD_STATE_CHANGED_ACTION * @hide */ public static final int NSD_STATE_DISABLED = 1; /** * Network service discovery is enabled * * @see #NSD_STATE_CHANGED_ACTION * @hide */ public static final int NSD_STATE_ENABLED = 2; private static final int BASE = Protocol.BASE_NSD_MANAGER; /** @hide */ Loading Loading @@ -188,6 +228,12 @@ public class NsdManager { /** @hide */ public static final int STOP_RESOLVE_SUCCEEDED = BASE + 23; /** @hide */ public static final int ENABLE = BASE + 24; /** @hide */ public static final int DISABLE = BASE + 25; /** * Create a new Nsd instance. Applications use * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve Loading Loading @@ -312,8 +358,8 @@ public class NsdManager { private DnsSdResolveListener mDnsSdResolveListener; private ActionListener mDnsSdStopResolveListener; AsyncChannel mAsyncChannel; ServiceHandler mHandler; private AsyncChannel mAsyncChannel; private ServiceHandler mHandler; class ServiceHandler extends Handler { ServiceHandler(Looper looper) { super(looper); Loading Loading @@ -594,6 +640,13 @@ public class NsdManager { c.mAsyncChannel.sendMessage(STOP_RESOLVE); } /** Internal use only @hide */ public void setEnabled(boolean enabled) { try { mService.setEnabled(enabled); } catch (RemoteException e) { } } /** * Get a reference to NetworkService handler. This is used to establish * an AsyncChannel communication with the service Loading core/java/android/provider/Settings.java +6 −0 Original line number Diff line number Diff line Loading @@ -3276,6 +3276,12 @@ public final class Settings { public static final String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS = "wifi_mobile_data_transition_wakelock_timeout_ms"; /** * Whether network service discovery is enabled. * @hide */ public static final String NSD_ON = "nsd_on"; /** * Whether background data usage is allowed by the user. See * ConnectivityManager for more info. Loading services/java/com/android/server/NsdService.java +324 −144 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ package com.android.server; import android.content.Context; import android.content.ContentResolver; import android.content.Intent; import android.content.pm.PackageManager; import android.net.nsd.DnsSdServiceInfo; import android.net.nsd.DnsSdTxtRecord; Loading @@ -28,6 +30,7 @@ import android.os.HandlerThread; import android.os.Message; import android.os.Messenger; import android.os.IBinder; import android.provider.Settings; import android.util.Slog; import java.io.FileDescriptor; Loading @@ -41,6 +44,9 @@ import java.util.concurrent.CountDownLatch; import com.android.internal.app.IBatteryStats; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; import com.android.internal.util.State; import com.android.internal.util.StateMachine; import com.android.server.am.BatteryStatsService; import com.android.server.NativeDaemonConnector.Command; import com.android.internal.R; Loading @@ -58,6 +64,8 @@ public class NsdService extends INsdManager.Stub { private static final boolean DBG = true; private Context mContext; private ContentResolver mContentResolver; private NsdStateMachine mNsdStateMachine; /** * Clients receiving asynchronous messages Loading @@ -69,19 +77,55 @@ public class NsdService extends INsdManager.Stub { private int INVALID_ID = 0; private int mUniqueId = 1; /** * Handles client(app) connections */ private class AsyncServiceHandler extends Handler { private static final int BASE = Protocol.BASE_NSD_MANAGER; private static final int CMD_TO_STRING_COUNT = NsdManager.STOP_RESOLVE - BASE + 1; private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT]; static { sCmdToString[NsdManager.DISCOVER_SERVICES - BASE] = "DISCOVER"; sCmdToString[NsdManager.STOP_DISCOVERY - BASE] = "STOP-DISCOVER"; sCmdToString[NsdManager.REGISTER_SERVICE - BASE] = "REGISTER"; sCmdToString[NsdManager.UNREGISTER_SERVICE - BASE] = "UNREGISTER"; sCmdToString[NsdManager.RESOLVE_SERVICE - BASE] = "RESOLVE"; sCmdToString[NsdManager.STOP_RESOLVE - BASE] = "STOP-RESOLVE"; } AsyncServiceHandler(android.os.Looper looper) { super(looper); private static String cmdToString(int cmd) { cmd -= BASE; if ((cmd >= 0) && (cmd < sCmdToString.length)) { return sCmdToString[cmd]; } else { return null; } } private class NsdStateMachine extends StateMachine { private DefaultState mDefaultState = new DefaultState(); private DisabledState mDisabledState = new DisabledState(); private EnabledState mEnabledState = new EnabledState(); @Override public void handleMessage(Message msg) { ClientInfo clientInfo; DnsSdServiceInfo servInfo; protected String getMessageInfo(Message msg) { return cmdToString(msg.what); } NsdStateMachine(String name) { super(name); addState(mDefaultState); addState(mDisabledState, mDefaultState); addState(mEnabledState, mDefaultState); if (isNsdEnabled()) { setInitialState(mEnabledState); } else { setInitialState(mDisabledState); } setProcessedMessagesSize(25); } class DefaultState extends State { @Override public boolean processMessage(Message msg) { switch (msg.what) { case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { Loading @@ -89,9 +133,6 @@ public class NsdService extends INsdManager.Stub { if (DBG) Slog.d(TAG, "New client listening to asynchronous messages"); c.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED); ClientInfo cInfo = new ClientInfo(c, msg.replyTo); if (mClients.size() == 0) { startMDnsDaemon(); } mClients.put(msg.replyTo, cInfo); } else { Slog.e(TAG, "Client connection failure, error=" + msg.arg1); Loading @@ -104,13 +145,102 @@ public class NsdService extends INsdManager.Stub { if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1); } mClients.remove(msg.replyTo); if (mClients.size() == 0) { stopMDnsDaemon(); } break; case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: AsyncChannel ac = new AsyncChannel(); ac.connect(mContext, this, msg.replyTo); ac.connect(mContext, getHandler(), msg.replyTo); break; case NsdManager.DISCOVER_SERVICES: mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, NsdManager.BUSY); break; case NsdManager.STOP_DISCOVERY: mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, NsdManager.ERROR); break; case NsdManager.REGISTER_SERVICE: mReplyChannel.replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, NsdManager.ERROR); break; case NsdManager.UNREGISTER_SERVICE: mReplyChannel.replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, NsdManager.ERROR); break; case NsdManager.RESOLVE_SERVICE: mReplyChannel.replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, NsdManager.ERROR); break; case NsdManager.STOP_RESOLVE: mReplyChannel.replyToMessage(msg, NsdManager.STOP_RESOLVE_FAILED, NsdManager.ERROR); break; default: Slog.e(TAG, "Unhandled " + msg); return NOT_HANDLED; } return HANDLED; } } class DisabledState extends State { @Override public void enter() { sendNsdStateChangeBroadcast(false); } @Override public boolean processMessage(Message msg) { switch (msg.what) { case NsdManager.ENABLE: transitionTo(mEnabledState); break; default: return NOT_HANDLED; } return HANDLED; } } class EnabledState extends State { @Override public void enter() { sendNsdStateChangeBroadcast(true); if (mClients.size() > 0) { startMDnsDaemon(); } } @Override public void exit() { if (mClients.size() > 0) { stopMDnsDaemon(); } } @Override public boolean processMessage(Message msg) { ClientInfo clientInfo; DnsSdServiceInfo servInfo; boolean result = HANDLED; switch (msg.what) { case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: //First client if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL && mClients.size() == 0) { startMDnsDaemon(); } result = NOT_HANDLED; break; case AsyncChannel.CMD_CHANNEL_DISCONNECTED: //Last client if (mClients.size() == 1) { stopMDnsDaemon(); } result = NOT_HANDLED; break; case NsdManager.DISABLE: //TODO: cleanup clients transitionTo(mDisabledState); break; case NsdManager.DISCOVER_SERVICES: if (DBG) Slog.d(TAG, "Discover services"); Loading Loading @@ -173,7 +303,8 @@ public class NsdService extends INsdManager.Stub { int regId = msg.arg1; if (clientInfo.mRegisteredIds.remove(new Integer(regId)) && unregisterService(regId)) { mReplyChannel.replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_SUCCEEDED); mReplyChannel.replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_SUCCEEDED); } else { mReplyChannel.replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, NsdManager.ERROR); Loading Loading @@ -219,39 +350,69 @@ public class NsdService extends INsdManager.Stub { } break; default: Slog.d(TAG, "NsdServicehandler.handleMessage ignoring msg=" + msg); result = NOT_HANDLED; break; } return result; } } } private AsyncServiceHandler mAsyncServiceHandler; private NativeDaemonConnector mNativeConnector; private final CountDownLatch mNativeDaemonConnected = new CountDownLatch(1); private NsdService(Context context) { mContext = context; HandlerThread nsdThread = new HandlerThread("NsdService"); nsdThread.start(); mAsyncServiceHandler = new AsyncServiceHandler(nsdThread.getLooper()); mContentResolver = context.getContentResolver(); mNativeConnector = new NativeDaemonConnector(new NativeCallbackReceiver(), "mdns", 10, MDNS_TAG, 25); mNsdStateMachine = new NsdStateMachine(TAG); mNsdStateMachine.start(); Thread th = new Thread(mNativeConnector, MDNS_TAG); th.start(); } public static NsdService create(Context context) throws InterruptedException { NsdService service = new NsdService(context); /* service.mNativeDaemonConnected.await(); */ service.mNativeDaemonConnected.await(); return service; } public Messenger getMessenger() { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET, "NsdService"); return new Messenger(mAsyncServiceHandler); return new Messenger(mNsdStateMachine.getHandler()); } public void setEnabled(boolean enable) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL, "NsdService"); Settings.Secure.putInt(mContentResolver, Settings.Secure.NSD_ON, enable ? 1 : 0); if (enable) { mNsdStateMachine.sendMessage(NsdManager.ENABLE); } else { mNsdStateMachine.sendMessage(NsdManager.DISABLE); } } private void sendNsdStateChangeBroadcast(boolean enabled) { final Intent intent = new Intent(NsdManager.NSD_STATE_CHANGED_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); if (enabled) { intent.putExtra(NsdManager.EXTRA_NSD_STATE, NsdManager.NSD_STATE_ENABLED); } else { intent.putExtra(NsdManager.EXTRA_NSD_STATE, NsdManager.NSD_STATE_DISABLED); } mContext.sendStickyBroadcast(intent); } private boolean isNsdEnabled() { boolean ret = Settings.Secure.getInt(mContentResolver, Settings.Secure.NSD_ON, 1) == 1; if (DBG) Slog.d(TAG, "Network service discovery enabled " + ret); return ret; } private int getUniqueId() { Loading Loading @@ -522,7 +683,7 @@ public class NsdService extends INsdManager.Stub { } @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { pw.println("Permission Denial: can't dump ServiceDiscoverService from from pid=" Loading @@ -531,7 +692,12 @@ public class NsdService extends INsdManager.Stub { return; } pw.println("Internal state:"); for (ClientInfo client : mClients.values()) { pw.println("Client Info"); pw.println(client); } mNsdStateMachine.dump(fd, pw, args); } private ClientInfo getClientByDiscovery(int discoveryId) { Loading Loading @@ -579,5 +745,19 @@ public class NsdService extends INsdManager.Stub { mDiscoveryId = mResolveId = INVALID_ID; if (DBG) Slog.d(TAG, "New client, channel: " + c + " messenger: " + m); } @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("mChannel ").append(mChannel).append("\n"); sb.append("mMessenger ").append(mMessenger).append("\n"); sb.append("mDiscoveryId ").append(mDiscoveryId).append("\n"); sb.append("mResolveId ").append(mResolveId).append("\n"); sb.append("mResolvedService ").append(mResolvedService).append("\n"); for(int regId : mRegisteredIds) { sb.append("regId ").append(regId).append("\n"); } return sb.toString(); } } } Loading
core/java/android/net/nsd/INsdManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -26,4 +26,5 @@ import android.os.Messenger; interface INsdManager { Messenger getMessenger(); void setEnabled(boolean enable); }
core/java/android/net/nsd/NsdManager.java +55 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.net.nsd; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.content.Context; import android.os.Binder; import android.os.IBinder; Loading Loading @@ -133,6 +135,44 @@ public class NsdManager { private static final String TAG = "NsdManager"; INsdManager mService; /** * Broadcast intent action to indicate whether network service discovery is * enabled or disabled. An extra {@link #EXTRA_NSD_STATE} provides the state * information as int. * * @see #EXTRA_NSD_STATE * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String NSD_STATE_CHANGED_ACTION = "android.net.nsd.STATE_CHANGED"; /** * The lookup key for an int that indicates whether network service discovery is enabled * or disabled. Retrieve it with {@link android.content.Intent#getIntExtra(String,int)}. * * @see #NSD_STATE_DISABLED * @see #NSD_STATE_ENABLED * @hide */ public static final String EXTRA_NSD_STATE = "nsd_state"; /** * Network service discovery is disabled * * @see #NSD_STATE_CHANGED_ACTION * @hide */ public static final int NSD_STATE_DISABLED = 1; /** * Network service discovery is enabled * * @see #NSD_STATE_CHANGED_ACTION * @hide */ public static final int NSD_STATE_ENABLED = 2; private static final int BASE = Protocol.BASE_NSD_MANAGER; /** @hide */ Loading Loading @@ -188,6 +228,12 @@ public class NsdManager { /** @hide */ public static final int STOP_RESOLVE_SUCCEEDED = BASE + 23; /** @hide */ public static final int ENABLE = BASE + 24; /** @hide */ public static final int DISABLE = BASE + 25; /** * Create a new Nsd instance. Applications use * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve Loading Loading @@ -312,8 +358,8 @@ public class NsdManager { private DnsSdResolveListener mDnsSdResolveListener; private ActionListener mDnsSdStopResolveListener; AsyncChannel mAsyncChannel; ServiceHandler mHandler; private AsyncChannel mAsyncChannel; private ServiceHandler mHandler; class ServiceHandler extends Handler { ServiceHandler(Looper looper) { super(looper); Loading Loading @@ -594,6 +640,13 @@ public class NsdManager { c.mAsyncChannel.sendMessage(STOP_RESOLVE); } /** Internal use only @hide */ public void setEnabled(boolean enabled) { try { mService.setEnabled(enabled); } catch (RemoteException e) { } } /** * Get a reference to NetworkService handler. This is used to establish * an AsyncChannel communication with the service Loading
core/java/android/provider/Settings.java +6 −0 Original line number Diff line number Diff line Loading @@ -3276,6 +3276,12 @@ public final class Settings { public static final String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS = "wifi_mobile_data_transition_wakelock_timeout_ms"; /** * Whether network service discovery is enabled. * @hide */ public static final String NSD_ON = "nsd_on"; /** * Whether background data usage is allowed by the user. See * ConnectivityManager for more info. Loading
services/java/com/android/server/NsdService.java +324 −144 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ package com.android.server; import android.content.Context; import android.content.ContentResolver; import android.content.Intent; import android.content.pm.PackageManager; import android.net.nsd.DnsSdServiceInfo; import android.net.nsd.DnsSdTxtRecord; Loading @@ -28,6 +30,7 @@ import android.os.HandlerThread; import android.os.Message; import android.os.Messenger; import android.os.IBinder; import android.provider.Settings; import android.util.Slog; import java.io.FileDescriptor; Loading @@ -41,6 +44,9 @@ import java.util.concurrent.CountDownLatch; import com.android.internal.app.IBatteryStats; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; import com.android.internal.util.State; import com.android.internal.util.StateMachine; import com.android.server.am.BatteryStatsService; import com.android.server.NativeDaemonConnector.Command; import com.android.internal.R; Loading @@ -58,6 +64,8 @@ public class NsdService extends INsdManager.Stub { private static final boolean DBG = true; private Context mContext; private ContentResolver mContentResolver; private NsdStateMachine mNsdStateMachine; /** * Clients receiving asynchronous messages Loading @@ -69,19 +77,55 @@ public class NsdService extends INsdManager.Stub { private int INVALID_ID = 0; private int mUniqueId = 1; /** * Handles client(app) connections */ private class AsyncServiceHandler extends Handler { private static final int BASE = Protocol.BASE_NSD_MANAGER; private static final int CMD_TO_STRING_COUNT = NsdManager.STOP_RESOLVE - BASE + 1; private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT]; static { sCmdToString[NsdManager.DISCOVER_SERVICES - BASE] = "DISCOVER"; sCmdToString[NsdManager.STOP_DISCOVERY - BASE] = "STOP-DISCOVER"; sCmdToString[NsdManager.REGISTER_SERVICE - BASE] = "REGISTER"; sCmdToString[NsdManager.UNREGISTER_SERVICE - BASE] = "UNREGISTER"; sCmdToString[NsdManager.RESOLVE_SERVICE - BASE] = "RESOLVE"; sCmdToString[NsdManager.STOP_RESOLVE - BASE] = "STOP-RESOLVE"; } AsyncServiceHandler(android.os.Looper looper) { super(looper); private static String cmdToString(int cmd) { cmd -= BASE; if ((cmd >= 0) && (cmd < sCmdToString.length)) { return sCmdToString[cmd]; } else { return null; } } private class NsdStateMachine extends StateMachine { private DefaultState mDefaultState = new DefaultState(); private DisabledState mDisabledState = new DisabledState(); private EnabledState mEnabledState = new EnabledState(); @Override public void handleMessage(Message msg) { ClientInfo clientInfo; DnsSdServiceInfo servInfo; protected String getMessageInfo(Message msg) { return cmdToString(msg.what); } NsdStateMachine(String name) { super(name); addState(mDefaultState); addState(mDisabledState, mDefaultState); addState(mEnabledState, mDefaultState); if (isNsdEnabled()) { setInitialState(mEnabledState); } else { setInitialState(mDisabledState); } setProcessedMessagesSize(25); } class DefaultState extends State { @Override public boolean processMessage(Message msg) { switch (msg.what) { case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { Loading @@ -89,9 +133,6 @@ public class NsdService extends INsdManager.Stub { if (DBG) Slog.d(TAG, "New client listening to asynchronous messages"); c.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED); ClientInfo cInfo = new ClientInfo(c, msg.replyTo); if (mClients.size() == 0) { startMDnsDaemon(); } mClients.put(msg.replyTo, cInfo); } else { Slog.e(TAG, "Client connection failure, error=" + msg.arg1); Loading @@ -104,13 +145,102 @@ public class NsdService extends INsdManager.Stub { if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1); } mClients.remove(msg.replyTo); if (mClients.size() == 0) { stopMDnsDaemon(); } break; case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: AsyncChannel ac = new AsyncChannel(); ac.connect(mContext, this, msg.replyTo); ac.connect(mContext, getHandler(), msg.replyTo); break; case NsdManager.DISCOVER_SERVICES: mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, NsdManager.BUSY); break; case NsdManager.STOP_DISCOVERY: mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, NsdManager.ERROR); break; case NsdManager.REGISTER_SERVICE: mReplyChannel.replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, NsdManager.ERROR); break; case NsdManager.UNREGISTER_SERVICE: mReplyChannel.replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, NsdManager.ERROR); break; case NsdManager.RESOLVE_SERVICE: mReplyChannel.replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, NsdManager.ERROR); break; case NsdManager.STOP_RESOLVE: mReplyChannel.replyToMessage(msg, NsdManager.STOP_RESOLVE_FAILED, NsdManager.ERROR); break; default: Slog.e(TAG, "Unhandled " + msg); return NOT_HANDLED; } return HANDLED; } } class DisabledState extends State { @Override public void enter() { sendNsdStateChangeBroadcast(false); } @Override public boolean processMessage(Message msg) { switch (msg.what) { case NsdManager.ENABLE: transitionTo(mEnabledState); break; default: return NOT_HANDLED; } return HANDLED; } } class EnabledState extends State { @Override public void enter() { sendNsdStateChangeBroadcast(true); if (mClients.size() > 0) { startMDnsDaemon(); } } @Override public void exit() { if (mClients.size() > 0) { stopMDnsDaemon(); } } @Override public boolean processMessage(Message msg) { ClientInfo clientInfo; DnsSdServiceInfo servInfo; boolean result = HANDLED; switch (msg.what) { case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: //First client if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL && mClients.size() == 0) { startMDnsDaemon(); } result = NOT_HANDLED; break; case AsyncChannel.CMD_CHANNEL_DISCONNECTED: //Last client if (mClients.size() == 1) { stopMDnsDaemon(); } result = NOT_HANDLED; break; case NsdManager.DISABLE: //TODO: cleanup clients transitionTo(mDisabledState); break; case NsdManager.DISCOVER_SERVICES: if (DBG) Slog.d(TAG, "Discover services"); Loading Loading @@ -173,7 +303,8 @@ public class NsdService extends INsdManager.Stub { int regId = msg.arg1; if (clientInfo.mRegisteredIds.remove(new Integer(regId)) && unregisterService(regId)) { mReplyChannel.replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_SUCCEEDED); mReplyChannel.replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_SUCCEEDED); } else { mReplyChannel.replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, NsdManager.ERROR); Loading Loading @@ -219,39 +350,69 @@ public class NsdService extends INsdManager.Stub { } break; default: Slog.d(TAG, "NsdServicehandler.handleMessage ignoring msg=" + msg); result = NOT_HANDLED; break; } return result; } } } private AsyncServiceHandler mAsyncServiceHandler; private NativeDaemonConnector mNativeConnector; private final CountDownLatch mNativeDaemonConnected = new CountDownLatch(1); private NsdService(Context context) { mContext = context; HandlerThread nsdThread = new HandlerThread("NsdService"); nsdThread.start(); mAsyncServiceHandler = new AsyncServiceHandler(nsdThread.getLooper()); mContentResolver = context.getContentResolver(); mNativeConnector = new NativeDaemonConnector(new NativeCallbackReceiver(), "mdns", 10, MDNS_TAG, 25); mNsdStateMachine = new NsdStateMachine(TAG); mNsdStateMachine.start(); Thread th = new Thread(mNativeConnector, MDNS_TAG); th.start(); } public static NsdService create(Context context) throws InterruptedException { NsdService service = new NsdService(context); /* service.mNativeDaemonConnected.await(); */ service.mNativeDaemonConnected.await(); return service; } public Messenger getMessenger() { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET, "NsdService"); return new Messenger(mAsyncServiceHandler); return new Messenger(mNsdStateMachine.getHandler()); } public void setEnabled(boolean enable) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL, "NsdService"); Settings.Secure.putInt(mContentResolver, Settings.Secure.NSD_ON, enable ? 1 : 0); if (enable) { mNsdStateMachine.sendMessage(NsdManager.ENABLE); } else { mNsdStateMachine.sendMessage(NsdManager.DISABLE); } } private void sendNsdStateChangeBroadcast(boolean enabled) { final Intent intent = new Intent(NsdManager.NSD_STATE_CHANGED_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); if (enabled) { intent.putExtra(NsdManager.EXTRA_NSD_STATE, NsdManager.NSD_STATE_ENABLED); } else { intent.putExtra(NsdManager.EXTRA_NSD_STATE, NsdManager.NSD_STATE_DISABLED); } mContext.sendStickyBroadcast(intent); } private boolean isNsdEnabled() { boolean ret = Settings.Secure.getInt(mContentResolver, Settings.Secure.NSD_ON, 1) == 1; if (DBG) Slog.d(TAG, "Network service discovery enabled " + ret); return ret; } private int getUniqueId() { Loading Loading @@ -522,7 +683,7 @@ public class NsdService extends INsdManager.Stub { } @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { pw.println("Permission Denial: can't dump ServiceDiscoverService from from pid=" Loading @@ -531,7 +692,12 @@ public class NsdService extends INsdManager.Stub { return; } pw.println("Internal state:"); for (ClientInfo client : mClients.values()) { pw.println("Client Info"); pw.println(client); } mNsdStateMachine.dump(fd, pw, args); } private ClientInfo getClientByDiscovery(int discoveryId) { Loading Loading @@ -579,5 +745,19 @@ public class NsdService extends INsdManager.Stub { mDiscoveryId = mResolveId = INVALID_ID; if (DBG) Slog.d(TAG, "New client, channel: " + c + " messenger: " + m); } @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("mChannel ").append(mChannel).append("\n"); sb.append("mMessenger ").append(mMessenger).append("\n"); sb.append("mDiscoveryId ").append(mDiscoveryId).append("\n"); sb.append("mResolveId ").append(mResolveId).append("\n"); sb.append("mResolvedService ").append(mResolvedService).append("\n"); for(int regId : mRegisteredIds) { sb.append("regId ").append(regId).append("\n"); } return sb.toString(); } } }