Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d640465c authored by Hugo Benichi's avatar Hugo Benichi Committed by android-build-merger
Browse files

Merge "NsdService: disentangle NativeDaemonConnector from ctor" am: fa97f11b am: 47748b75

am: 5d0bd135

Change-Id: Ic8ddf92c7c64d4214a75bea6d6e5083f4612a76a
parents be014da6 5d0bd135
Loading
Loading
Loading
Loading
+81 −106
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import android.util.SparseArray;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.HashMap;
import java.util.concurrent.CountDownLatch;

@@ -65,8 +66,8 @@ public class NsdService extends INsdManager.Stub {
    private final Context mContext;
    private final NsdSettings mNsdSettings;
    private final NsdStateMachine mNsdStateMachine;
    private final NativeDaemonConnector mNativeConnector;
    private final CountDownLatch mNativeDaemonConnected = new CountDownLatch(1);
    private final DaemonConnection mDaemon;
    private final NativeCallbackReceiver mDaemonCallback;

    /**
     * Clients receiving asynchronous messages
@@ -546,18 +547,13 @@ public class NsdService extends INsdManager.Stub {
    }

    @VisibleForTesting
    NsdService(Context ctx, NsdSettings settings, Handler handler) {
    NsdService(Context ctx, NsdSettings settings, Handler handler, DaemonConnectionSupplier fn) {
        mContext = ctx;
        mNsdSettings = settings;

        NativeCallbackReceiver callback = new NativeCallbackReceiver();
        mNativeConnector = new NativeDaemonConnector(callback, "mdns", 10, MDNS_TAG, 25, null);

        mNsdStateMachine = new NsdStateMachine(TAG, handler);
        mNsdStateMachine.start();

        Thread th = new Thread(mNativeConnector, MDNS_TAG);
        th.start();
        mDaemonCallback = new NativeCallbackReceiver();
        mDaemon = fn.get(mDaemonCallback);
    }

    public static NsdService create(Context context) throws InterruptedException {
@@ -565,8 +561,8 @@ public class NsdService extends INsdManager.Stub {
        HandlerThread thread = new HandlerThread(TAG);
        thread.start();
        Handler handler = new Handler(thread.getLooper());
        NsdService service = new NsdService(context, settings, handler);
        service.mNativeDaemonConnected.await();
        NsdService service = new NsdService(context, settings, handler, DaemonConnection::new);
        service.mDaemonCallback.awaitConnection();
        return service;
    }

@@ -665,14 +661,23 @@ public class NsdService extends INsdManager.Stub {
    }

    class NativeCallbackReceiver implements INativeDaemonConnectorCallbacks {
        private final CountDownLatch connected = new CountDownLatch(1);

        public void awaitConnection() throws InterruptedException {
            connected.await();
        }

        @Override
        public void onDaemonConnected() {
            mNativeDaemonConnected.countDown();
            connected.countDown();
        }

        @Override
        public boolean onCheckHoldWakeLock(int code) {
            return false;
        }

        @Override
        public boolean onEvent(int code, String raw, String[] cooked) {
            // TODO: NDC translates a message to a callback, we could enhance NDC to
            // directly interact with a state machine through messages
@@ -682,132 +687,102 @@ public class NsdService extends INsdManager.Stub {
        }
    }

    private boolean startMDnsDaemon() {
        if (DBG) Slog.d(TAG, "startMDnsDaemon");
        try {
            mNativeConnector.execute("mdnssd", "start-service");
        } catch(NativeDaemonConnectorException e) {
            Slog.e(TAG, "Failed to start daemon" + e);
            return false;
    interface DaemonConnectionSupplier {
        DaemonConnection get(NativeCallbackReceiver callback);
    }
        return true;

    @VisibleForTesting
    public static class DaemonConnection {
        final NativeDaemonConnector mNativeConnector;

        DaemonConnection(NativeCallbackReceiver callback) {
            mNativeConnector = new NativeDaemonConnector(callback, "mdns", 10, MDNS_TAG, 25, null);
            new Thread(mNativeConnector, MDNS_TAG).start();
        }

    private boolean stopMDnsDaemon() {
        if (DBG) Slog.d(TAG, "stopMDnsDaemon");
        public boolean execute(Object... args) {
            if (DBG) {
                Slog.d(TAG, "mdnssd " + Arrays.toString(args));
            }
            try {
            mNativeConnector.execute("mdnssd", "stop-service");
                mNativeConnector.execute("mdnssd", args);
            } catch (NativeDaemonConnectorException e) {
            Slog.e(TAG, "Failed to start daemon" + e);
                Slog.e(TAG, "Failed to execute mdnssd " + Arrays.toString(args), e);
                return false;
            }
            return true;
        }

    private boolean registerService(int regId, NsdServiceInfo service) {
        if (DBG) Slog.d(TAG, "registerService: " + regId + " " + service);
        public boolean execute(Command cmd) {
            if (DBG) {
                Slog.d(TAG, cmd.toString());
            }
            try {
            Command cmd = new Command("mdnssd", "register", regId, service.getServiceName(),
                    service.getServiceType(), service.getPort(),
                    Base64.encodeToString(service.getTxtRecord(), Base64.DEFAULT)
                            .replace("\n", ""));

                mNativeConnector.execute(cmd);
            } catch (NativeDaemonConnectorException e) {
            Slog.e(TAG, "Failed to execute registerService " + e);
                Slog.e(TAG, "Failed to execute " + cmd, e);
                return false;
            }
            return true;
        }
    }

    private boolean unregisterService(int regId) {
        if (DBG) Slog.d(TAG, "unregisterService: " + regId);
        try {
            mNativeConnector.execute("mdnssd", "stop-register", regId);
        } catch(NativeDaemonConnectorException e) {
            Slog.e(TAG, "Failed to execute unregisterService " + e);
            return false;
    private boolean startMDnsDaemon() {
        return mDaemon.execute("start-service");
    }
        return true;

    private boolean stopMDnsDaemon() {
        return mDaemon.execute("stop-service");
    }

    private boolean registerService(int regId, NsdServiceInfo service) {
        if (DBG) {
            Slog.d(TAG, "registerService: " + regId + " " + service);
        }
        String name = service.getServiceName();
        String type = service.getServiceType();
        int port = service.getPort();
        byte[] textRecord = service.getTxtRecord();
        String record = Base64.encodeToString(textRecord, Base64.DEFAULT).replace("\n", "");
        Command cmd = new Command("mdnssd", "register", regId, name, type, port, record);
        return mDaemon.execute(cmd);
    }

    private boolean unregisterService(int regId) {
        return mDaemon.execute("stop-register", regId);
    }

    private boolean updateService(int regId, DnsSdTxtRecord t) {
        if (DBG) Slog.d(TAG, "updateService: " + regId + " " + t);
        try {
            if (t == null) return false;
            mNativeConnector.execute("mdnssd", "update", regId, t.size(), t.getRawData());
        } catch(NativeDaemonConnectorException e) {
            Slog.e(TAG, "Failed to updateServices " + e);
        if (t == null) {
            return false;
        }
        return true;
        return mDaemon.execute("update", regId, t.size(), t.getRawData());
    }

    private boolean discoverServices(int discoveryId, String serviceType) {
        if (DBG) Slog.d(TAG, "discoverServices: " + discoveryId + " " + serviceType);
        try {
            mNativeConnector.execute("mdnssd", "discover", discoveryId, serviceType);
        } catch(NativeDaemonConnectorException e) {
            Slog.e(TAG, "Failed to discoverServices " + e);
            return false;
        }
        return true;
        return mDaemon.execute("discover", discoveryId, serviceType);
    }

    private boolean stopServiceDiscovery(int discoveryId) {
        if (DBG) Slog.d(TAG, "stopServiceDiscovery: " + discoveryId);
        try {
            mNativeConnector.execute("mdnssd", "stop-discover", discoveryId);
        } catch(NativeDaemonConnectorException e) {
            Slog.e(TAG, "Failed to stopServiceDiscovery " + e);
            return false;
        }
        return true;
        return mDaemon.execute("stop-discover", discoveryId);
    }

    private boolean resolveService(int resolveId, NsdServiceInfo service) {
        if (DBG) Slog.d(TAG, "resolveService: " + resolveId + " " + service);
        try {
            mNativeConnector.execute("mdnssd", "resolve", resolveId, service.getServiceName(),
                    service.getServiceType(), "local.");
        } catch(NativeDaemonConnectorException e) {
            Slog.e(TAG, "Failed to resolveService " + e);
            return false;
        }
        return true;
        String name = service.getServiceName();
        String type = service.getServiceType();
        return mDaemon.execute("resolve", resolveId, name, type, "local.");
    }

    private boolean stopResolveService(int resolveId) {
        if (DBG) Slog.d(TAG, "stopResolveService: " + resolveId);
        try {
            mNativeConnector.execute("mdnssd", "stop-resolve", resolveId);
        } catch(NativeDaemonConnectorException e) {
            Slog.e(TAG, "Failed to stop resolve " + e);
            return false;
        }
        return true;
        return mDaemon.execute("stop-resolve", resolveId);
    }

    private boolean getAddrInfo(int resolveId, String hostname) {
        if (DBG) Slog.d(TAG, "getAdddrInfo: " + resolveId);
        try {
            mNativeConnector.execute("mdnssd", "getaddrinfo", resolveId, hostname);
        } catch(NativeDaemonConnectorException e) {
            Slog.e(TAG, "Failed to getAddrInfo " + e);
            return false;
        }
        return true;
        return mDaemon.execute("getaddrinfo", resolveId, hostname);
    }

    private boolean stopGetAddrInfo(int resolveId) {
        if (DBG) Slog.d(TAG, "stopGetAdddrInfo: " + resolveId);
        try {
            mNativeConnector.execute("mdnssd", "stop-getaddrinfo", resolveId);
        } catch(NativeDaemonConnectorException e) {
            Slog.e(TAG, "Failed to stopGetAddrInfo " + e);
            return false;
        }
        return true;
        return mDaemon.execute("stop-getaddrinfo", resolveId);
    }

    @Override
+22 −2
Original line number Diff line number Diff line
@@ -16,6 +16,11 @@

package com.android.server;

import static org.mockito.Mockito.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.os.Handler;
@@ -25,6 +30,9 @@ import android.os.test.TestLooper;
import android.content.Context;
import android.content.ContentResolver;
import android.net.nsd.NsdManager;
import com.android.server.NsdService.DaemonConnection;
import com.android.server.NsdService.DaemonConnectionSupplier;
import com.android.server.NsdService.NativeCallbackReceiver;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Before;
@@ -34,7 +42,6 @@ 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
@@ -45,6 +52,8 @@ public class NsdServiceTest {
    @Mock Context mContext;
    @Mock ContentResolver mResolver;
    @Mock NsdService.NsdSettings mSettings;
    @Mock DaemonConnection mDaemon;
    NativeCallbackReceiver mDaemonCallback;
    TestLooper mLooper;
    TestHandler mHandler;

@@ -58,8 +67,13 @@ public class NsdServiceTest {

    @Test
    public void testClientsCanConnect() {
        when(mSettings.isEnabled()).thenReturn(true);

        NsdService service = makeService();

        NsdManager client1 = connectClient(service);
        verify(mDaemon, timeout(100).times(1)).execute("start-service");

        NsdManager client2 = connectClient(service);

        // TODO: disconnect client1
@@ -67,7 +81,13 @@ public class NsdServiceTest {
    }

    NsdService makeService() {
        return new NsdService(mContext, mSettings, mHandler);
        DaemonConnectionSupplier supplier = (callback) -> {
            mDaemonCallback = callback;
            return mDaemon;
        };
        NsdService service = new NsdService(mContext, mSettings, mHandler, supplier);
        verify(mDaemon, never()).execute(any(String.class));
        return service;
    }

    NsdManager connectClient(NsdService service) {