diff options
| -rw-r--r-- | services/core/java/com/android/server/NsdService.java | 60 | ||||
| -rw-r--r-- | tests/net/java/android/net/nsd/NsdServiceTest.java | 93 |
2 files changed, 138 insertions, 15 deletions
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java index bb530fb8c13f..77e4da653334 100644 --- a/services/core/java/com/android/server/NsdService.java +++ b/services/core/java/com/android/server/NsdService.java @@ -26,6 +26,8 @@ import android.net.nsd.DnsSdTxtRecord; import android.net.nsd.INsdManager; import android.net.nsd.NsdManager; import android.os.Binder; +import android.os.HandlerThread; +import android.os.Handler; import android.os.Message; import android.os.Messenger; import android.os.UserHandle; @@ -40,6 +42,7 @@ import java.net.InetAddress; import java.util.HashMap; import java.util.concurrent.CountDownLatch; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.AsyncChannel; import com.android.internal.util.DumpUtils; import com.android.internal.util.Protocol; @@ -60,7 +63,7 @@ public class NsdService extends INsdManager.Stub { private static final boolean DBG = true; private final Context mContext; - private final ContentResolver mContentResolver; + private final NsdSettings mNsdSettings; private final NsdStateMachine mNsdStateMachine; private final NativeDaemonConnector mNativeConnector; private final CountDownLatch mNativeDaemonConnected = new CountDownLatch(1); @@ -109,8 +112,8 @@ public class NsdService extends INsdManager.Stub { false, contentObserver); } - NsdStateMachine(String name) { - super(name); + NsdStateMachine(String name, Handler handler) { + super(name, handler); addState(mDefaultState); addState(mDisabledState, mDefaultState); addState(mEnabledState, mDefaultState); @@ -542,14 +545,15 @@ public class NsdService extends INsdManager.Stub { return sb.toString(); } - private NsdService(Context context) { - mContext = context; - mContentResolver = context.getContentResolver(); + @VisibleForTesting + NsdService(Context ctx, NsdSettings settings, Handler handler) { + mContext = ctx; + mNsdSettings = settings; - mNativeConnector = new NativeDaemonConnector(new NativeCallbackReceiver(), "mdns", 10, - MDNS_TAG, 25, null); + NativeCallbackReceiver callback = new NativeCallbackReceiver(); + mNativeConnector = new NativeDaemonConnector(callback, "mdns", 10, MDNS_TAG, 25, null); - mNsdStateMachine = new NsdStateMachine(TAG); + mNsdStateMachine = new NsdStateMachine(TAG, handler); mNsdStateMachine.start(); Thread th = new Thread(mNativeConnector, MDNS_TAG); @@ -557,21 +561,24 @@ public class NsdService extends INsdManager.Stub { } public static NsdService create(Context context) throws InterruptedException { - NsdService service = new NsdService(context); + NsdSettings settings = NsdSettings.makeDefault(context); + HandlerThread thread = new HandlerThread(TAG); + thread.start(); + Handler handler = new Handler(thread.getLooper()); + NsdService service = new NsdService(context, settings, handler); service.mNativeDaemonConnected.await(); return service; } public Messenger getMessenger() { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET, - "NsdService"); + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET, "NsdService"); return new Messenger(mNsdStateMachine.getHandler()); } public void setEnabled(boolean enable) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL, "NsdService"); - Settings.Global.putInt(mContentResolver, Settings.Global.NSD_ON, enable ? 1 : 0); + mNsdSettings.putEnabledStatus(enable); if (enable) { mNsdStateMachine.sendMessage(NsdManager.ENABLE); } else { @@ -591,8 +598,10 @@ public class NsdService extends INsdManager.Stub { } private boolean isNsdEnabled() { - boolean ret = Settings.Global.getInt(mContentResolver, Settings.Global.NSD_ON, 1) == 1; - if (DBG) Slog.d(TAG, "Network service discovery enabled " + ret); + boolean ret = mNsdSettings.isEnabled(); + if (DBG) { + Slog.d(TAG, "Network service discovery is " + (ret ? "enabled" : "disabled")); + } return ret; } @@ -922,4 +931,25 @@ public class NsdService extends INsdManager.Stub { return -1; } } + + @VisibleForTesting + public interface NsdSettings { + boolean isEnabled(); + void putEnabledStatus(boolean isEnabled); + + static NsdSettings makeDefault(Context context) { + ContentResolver resolver = context.getContentResolver(); + return new NsdSettings() { + @Override + public boolean isEnabled() { + return Settings.Global.getInt(resolver, Settings.Global.NSD_ON, 1) == 1; + } + + @Override + public void putEnabledStatus(boolean isEnabled) { + Settings.Global.putInt(resolver, Settings.Global.NSD_ON, isEnabled ? 1 : 0); + } + }; + } + } } diff --git a/tests/net/java/android/net/nsd/NsdServiceTest.java b/tests/net/java/android/net/nsd/NsdServiceTest.java new file mode 100644 index 000000000000..64466bf69dcd --- /dev/null +++ b/tests/net/java/android/net/nsd/NsdServiceTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import static org.mockito.Mockito.when; + +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.test.TestLooper; +import android.content.Context; +import android.content.ContentResolver; +import android.net.nsd.NsdManager; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +// TODOs: +// - test daemon connection +// - test client disconnects +// - test client can send requests and receive replies +// - test NSD_ON ENABLE/DISABLED listening +@RunWith(AndroidJUnit4.class) +@SmallTest +public class NsdServiceTest { + + @Mock Context mContext; + @Mock ContentResolver mResolver; + @Mock NsdService.NsdSettings mSettings; + TestLooper mLooper; + TestHandler mHandler; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mLooper = new TestLooper(); + mHandler = new TestHandler(mLooper.getLooper()); + when(mContext.getContentResolver()).thenReturn(mResolver); + } + + @Test + public void testClientsCanConnect() { + NsdService service = makeService(); + NsdManager client1 = connectClient(service); + NsdManager client2 = connectClient(service); + + // TODO: disconnect client1 + // TODO: disconnect client2 + } + + NsdService makeService() { + return new NsdService(mContext, mSettings, mHandler); + } + + NsdManager connectClient(NsdService service) { + mLooper.startAutoDispatch(); + NsdManager client = new NsdManager(mContext, service); + mLooper.stopAutoDispatch(); + return client; + } + + public static class TestHandler extends Handler { + public Message lastMessage; + + TestHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + lastMessage = obtainMessage(); + lastMessage.copyFrom(msg); + } + } +} |