Merge "Fix Automated API Review issues."
diff --git a/core/java/android/net/CaptivePortal.java b/core/java/android/net/CaptivePortal.java
index ba7323d..ebd8a7e 100644
--- a/core/java/android/net/CaptivePortal.java
+++ b/core/java/android/net/CaptivePortal.java
@@ -15,6 +15,7 @@
  */
 package android.net;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.os.IBinder;
@@ -65,7 +66,7 @@
     /** @hide */
     @SystemApi
     @TestApi
-    public CaptivePortal(IBinder binder) {
+    public CaptivePortal(@NonNull IBinder binder) {
         mBinder = binder;
     }
 
@@ -142,7 +143,7 @@
      */
     @SystemApi
     @TestApi
-    public void logEvent(int eventId, String packageName) {
+    public void logEvent(int eventId, @NonNull String packageName) {
         try {
             ICaptivePortal.Stub.asInterface(mBinder).logEvent(eventId, packageName);
         } catch (RemoteException e) {
diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java
index 99cf3a9..0728d83 100644
--- a/core/java/android/net/StaticIpConfiguration.java
+++ b/core/java/android/net/StaticIpConfiguration.java
@@ -16,6 +16,8 @@
 
 package android.net;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
@@ -53,22 +55,26 @@
 public final class StaticIpConfiguration implements Parcelable {
     /** @hide */
     @UnsupportedAppUsage
+    @Nullable
     public LinkAddress ipAddress;
     /** @hide */
     @UnsupportedAppUsage
+    @Nullable
     public InetAddress gateway;
     /** @hide */
     @UnsupportedAppUsage
+    @NonNull
     public final ArrayList<InetAddress> dnsServers;
     /** @hide */
     @UnsupportedAppUsage
+    @Nullable
     public String domains;
 
     public StaticIpConfiguration() {
         dnsServers = new ArrayList<InetAddress>();
     }
 
-    public StaticIpConfiguration(StaticIpConfiguration source) {
+    public StaticIpConfiguration(@Nullable StaticIpConfiguration source) {
         this();
         if (source != null) {
             // All of these except dnsServers are immutable, so no need to make copies.
@@ -86,38 +92,38 @@
         domains = null;
     }
 
-    public LinkAddress getIpAddress() {
+    public @Nullable LinkAddress getIpAddress() {
         return ipAddress;
     }
 
-    public void setIpAddress(LinkAddress ipAddress) {
+    public void setIpAddress(@Nullable LinkAddress ipAddress) {
         this.ipAddress = ipAddress;
     }
 
-    public InetAddress getGateway() {
+    public @Nullable InetAddress getGateway() {
         return gateway;
     }
 
-    public void setGateway(InetAddress gateway) {
+    public void setGateway(@Nullable InetAddress gateway) {
         this.gateway = gateway;
     }
 
-    public List<InetAddress> getDnsServers() {
+    public @NonNull List<InetAddress> getDnsServers() {
         return dnsServers;
     }
 
-    public String getDomains() {
+    public @Nullable String getDomains() {
         return domains;
     }
 
-    public void setDomains(String newDomains) {
+    public void setDomains(@Nullable String newDomains) {
         domains = newDomains;
     }
 
     /**
      * Add a DNS server to this configuration.
      */
-    public void addDnsServer(InetAddress server) {
+    public void addDnsServer(@NonNull InetAddress server) {
         dnsServers.add(server);
     }
 
@@ -128,7 +134,7 @@
      * route to the gateway as well. This configuration is arguably invalid, but it used to work
      * in K and earlier, and other OSes appear to accept it.
      */
-    public List<RouteInfo> getRoutes(String iface) {
+    public @NonNull List<RouteInfo> getRoutes(String iface) {
         List<RouteInfo> routes = new ArrayList<RouteInfo>(3);
         if (ipAddress != null) {
             RouteInfo connectedRoute = new RouteInfo(ipAddress, null, iface);
@@ -150,7 +156,7 @@
      * IPv6 configuration) will not be included.
      * @hide
      */
-    public LinkProperties toLinkProperties(String iface) {
+    public @NonNull LinkProperties toLinkProperties(String iface) {
         LinkProperties lp = new LinkProperties();
         lp.setInterfaceName(iface);
         if (ipAddress != null) {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index d818dc4..52fcd4a 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2561,19 +2561,11 @@
 
                     final boolean partialConnectivity =
                             (msg.arg1 == NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY)
-                                    // If user accepts partial connectivity network, NetworkMonitor
-                                    // will skip https probing. It will make partial connectivity
-                                    // network becomes valid. But user still need to know this
-                                    // network is limited. So, it's needed to refer to
-                                    // acceptPartialConnectivity to add
-                                    // NET_CAPABILITY_PARTIAL_CONNECTIVITY into NetworkCapabilities
-                                    // of this network. So that user can see "Limited connection"
-                                    // in the settings.
                                     || (nai.networkMisc.acceptPartialConnectivity
                                             && nai.partialConnectivity);
                     // Once a network is determined to have partial connectivity, it cannot
                     // go back to full connectivity without a disconnect.
-                    final boolean partialConnectivityChange =
+                    final boolean partialConnectivityChanged =
                             (partialConnectivity && !nai.partialConnectivity);
 
                     final boolean valid = (msg.arg1 == NETWORK_TEST_RESULT_VALID);
@@ -2584,17 +2576,6 @@
                         nai.captivePortalLoginNotified = true;
                         showNetworkNotification(nai, NotificationType.LOGGED_IN);
                     }
-                    // If this network has just connected and partial connectivity has just been
-                    // detected, tell NetworkMonitor if the user accepted partial connectivity on a
-                    // previous connect.
-                    if ((msg.arg1 == NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY)
-                            && nai.networkMisc.acceptPartialConnectivity) {
-                        try {
-                            nai.networkMonitor().notifyAcceptPartialConnectivity();
-                        } catch (RemoteException e) {
-                            e.rethrowFromSystemServer();
-                        }
-                    }
 
                     final String redirectUrl = (msg.obj instanceof String) ? (String) msg.obj : "";
 
@@ -2624,7 +2605,7 @@
                             mNotifier.clearNotification(nai.network.netId,
                                     NotificationType.LOST_INTERNET);
                         }
-                    } else if (partialConnectivityChange) {
+                    } else if (partialConnectivityChanged) {
                         nai.partialConnectivity = partialConnectivity;
                         updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
                     }
@@ -3378,8 +3359,11 @@
             // Tear down the network.
             teardownUnneededNetwork(nai);
         } else {
+            // Inform NetworkMonitor that partial connectivity is acceptable. This will likely
+            // result in a partial connectivity result which will be processed by
+            // maybeHandleNetworkMonitorMessage.
             try {
-                nai.networkMonitor().notifyAcceptPartialConnectivity();
+                nai.networkMonitor().setAcceptPartialConnectivity();
             } catch (RemoteException e) {
                 e.rethrowFromSystemServer();
             }
@@ -3587,6 +3571,9 @@
         // because we're already prompting the user to sign in.
         if (nai == null || nai.everValidated || nai.everCaptivePortalDetected
                 || !nai.networkMisc.explicitlySelected || nai.networkMisc.acceptUnvalidated
+                // TODO: Once the value of acceptPartialConnectivity is moved to IpMemoryStore,
+                // we should reevaluate how to handle acceptPartialConnectivity when network just
+                // connected.
                 || nai.networkMisc.acceptPartialConnectivity) {
             return;
         }
@@ -6395,6 +6382,9 @@
             // NetworkMonitor seeing the correct LinkProperties when starting.
             // TODO: pass LinkProperties to the NetworkMonitor in the notifyNetworkConnected call.
             try {
+                if (networkAgent.networkMisc.acceptPartialConnectivity) {
+                    networkAgent.networkMonitor().setAcceptPartialConnectivity();
+                }
                 networkAgent.networkMonitor().notifyNetworkConnected();
             } catch (RemoteException e) {
                 e.rethrowFromSystemServer();
diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
index 35d6860..0e3d82c 100644
--- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
+++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
@@ -42,7 +42,6 @@
 import android.net.SocketKeepalive.InvalidPacketException;
 import android.net.SocketKeepalive.InvalidSocketException;
 import android.net.TcpKeepalivePacketData;
-import android.net.TcpKeepalivePacketData.TcpSocketInfo;
 import android.net.util.IpUtils;
 import android.os.Binder;
 import android.os.Handler;
@@ -492,19 +491,14 @@
             return;
         }
 
-        TcpKeepalivePacketData packet = null;
+        final TcpKeepalivePacketData packet;
         try {
-            TcpSocketInfo tsi = TcpKeepaliveController.switchToRepairMode(fd);
-            packet = TcpKeepalivePacketData.tcpKeepalivePacket(tsi);
+            packet = TcpKeepaliveController.getTcpKeepalivePacket(fd);
         } catch (InvalidPacketException | InvalidSocketException e) {
-            try {
-                TcpKeepaliveController.switchOutOfRepairMode(fd);
-            } catch (ErrnoException e1) {
-                Log.e(TAG, "Couldn't move fd out of repair mode after failure to start keepalive");
-            }
             notifyErrorCallback(cb, e.error);
             return;
         }
+
         KeepaliveInfo ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds,
                 KeepaliveInfo.TYPE_TCP, fd);
         Log.d(TAG, "Created keepalive: " + ki.toString());
diff --git a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
index 3e21b5b..f4d9006 100644
--- a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
+++ b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
@@ -28,8 +28,10 @@
 
 import android.annotation.NonNull;
 import android.net.NetworkUtils;
+import android.net.SocketKeepalive.InvalidPacketException;
 import android.net.SocketKeepalive.InvalidSocketException;
-import android.net.TcpKeepalivePacketData.TcpSocketInfo;
+import android.net.TcpKeepalivePacketData;
+import android.net.TcpKeepalivePacketDataParcelable;
 import android.net.TcpRepairWindow;
 import android.os.Handler;
 import android.os.MessageQueue;
@@ -44,7 +46,6 @@
 import com.android.server.connectivity.KeepaliveTracker.KeepaliveInfo;
 
 import java.io.FileDescriptor;
-import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 import java.net.SocketException;
@@ -103,26 +104,30 @@
         mFdHandlerQueue = connectivityServiceHandler.getLooper().getQueue();
     }
 
+    /** Build tcp keepalive packet. */
+    public static TcpKeepalivePacketData getTcpKeepalivePacket(@NonNull FileDescriptor fd)
+            throws InvalidPacketException, InvalidSocketException {
+        try {
+            final TcpKeepalivePacketDataParcelable tcpDetails = switchToRepairMode(fd);
+            return TcpKeepalivePacketData.tcpKeepalivePacket(tcpDetails);
+        } catch (InvalidPacketException | InvalidSocketException e) {
+            switchOutOfRepairMode(fd);
+            throw e;
+        }
+    }
     /**
-     * Switch the tcp socket to repair mode and query tcp socket information.
+     * Switch the tcp socket to repair mode and query detail tcp information.
      *
-     * @param fd the fd of socket on which to use keepalive offload
-     * @return a {@link TcpKeepalivePacketData#TcpSocketInfo} object for current
+     * @param fd the fd of socket on which to use keepalive offload.
+     * @return a {@link TcpKeepalivePacketData#TcpKeepalivePacketDataParcelable} object for current
      * tcp/ip information.
      */
-    // TODO : make this private. It's far too confusing that this gets called from outside
-    // at a time that nobody can understand.
-    public static TcpSocketInfo switchToRepairMode(FileDescriptor fd)
+    private static TcpKeepalivePacketDataParcelable switchToRepairMode(FileDescriptor fd)
             throws InvalidSocketException {
         if (DBG) Log.i(TAG, "switchToRepairMode to start tcp keepalive : " + fd);
+        final TcpKeepalivePacketDataParcelable tcpDetails = new TcpKeepalivePacketDataParcelable();
         final SocketAddress srcSockAddr;
         final SocketAddress dstSockAddr;
-        final InetAddress srcAddress;
-        final InetAddress dstAddress;
-        final int srcPort;
-        final int dstPort;
-        int seq;
-        final int ack;
         final TcpRepairWindow trw;
 
         // Query source address and port.
@@ -133,8 +138,8 @@
             throw new InvalidSocketException(ERROR_INVALID_SOCKET, e);
         }
         if (srcSockAddr instanceof InetSocketAddress) {
-            srcAddress = getAddress((InetSocketAddress) srcSockAddr);
-            srcPort = getPort((InetSocketAddress) srcSockAddr);
+            tcpDetails.srcAddress = getAddress((InetSocketAddress) srcSockAddr);
+            tcpDetails.srcPort = getPort((InetSocketAddress) srcSockAddr);
         } else {
             Log.e(TAG, "Invalid or mismatched SocketAddress");
             throw new InvalidSocketException(ERROR_INVALID_SOCKET);
@@ -147,8 +152,8 @@
             throw new InvalidSocketException(ERROR_INVALID_SOCKET, e);
         }
         if (dstSockAddr instanceof InetSocketAddress) {
-            dstAddress = getAddress((InetSocketAddress) dstSockAddr);
-            dstPort = getPort((InetSocketAddress) dstSockAddr);
+            tcpDetails.dstAddress = getAddress((InetSocketAddress) dstSockAddr);
+            tcpDetails.dstPort = getPort((InetSocketAddress) dstSockAddr);
         } else {
             Log.e(TAG, "Invalid or mismatched peer SocketAddress");
             throw new InvalidSocketException(ERROR_INVALID_SOCKET);
@@ -157,28 +162,37 @@
         // Query sequence and ack number
         dropAllIncomingPackets(fd, true);
         try {
-            // Enter tcp repair mode.
+            // Switch to tcp repair mode.
             Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR, TCP_REPAIR_ON);
+
             // Check if socket is idle.
             if (!isSocketIdle(fd)) {
+                Log.e(TAG, "Socket is not idle");
                 throw new InvalidSocketException(ERROR_SOCKET_NOT_IDLE);
             }
             // Query write sequence number from SEND_QUEUE.
             Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR_QUEUE, TCP_SEND_QUEUE);
-            seq = Os.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ);
+            tcpDetails.seq = Os.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ);
             // Query read sequence number from RECV_QUEUE.
             Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR_QUEUE, TCP_RECV_QUEUE);
-            ack = Os.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ);
+            tcpDetails.ack = Os.getsockoptInt(fd, IPPROTO_TCP, TCP_QUEUE_SEQ);
             // Switch to NO_QUEUE to prevent illegal socket read/write in repair mode.
             Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR_QUEUE, TCP_NO_QUEUE);
             // Finally, check if socket is still idle. TODO : this check needs to move to
             // after starting polling to prevent a race.
-            if (!isSocketIdle(fd)) {
+            if (!isReceiveQueueEmpty(fd)) {
+                Log.e(TAG, "Fatal: receive queue of this socket is not empty");
                 throw new InvalidSocketException(ERROR_INVALID_SOCKET);
             }
+            if (!isSendQueueEmpty(fd)) {
+                Log.e(TAG, "Socket is not idle");
+                throw new InvalidSocketException(ERROR_SOCKET_NOT_IDLE);
+            }
 
             // Query tcp window size.
             trw = NetworkUtils.getTcpRepairWindow(fd);
+            tcpDetails.rcvWnd = trw.rcvWnd;
+            tcpDetails.rcvWndScale = trw.rcvWndScale;
         } catch (ErrnoException e) {
             Log.e(TAG, "Exception reading TCP state from socket", e);
             if (e.errno == ENOPROTOOPT) {
@@ -194,10 +208,9 @@
 
         // Keepalive sequence number is last sequence number - 1. If it couldn't be retrieved,
         // then it must be set to -1, so decrement in all cases.
-        seq = seq - 1;
+        tcpDetails.seq = tcpDetails.seq - 1;
 
-        return new TcpSocketInfo(srcAddress, srcPort, dstAddress, dstPort, seq, ack, trw.rcvWnd,
-                trw.rcvWndScale);
+        return tcpDetails;
     }
 
     /**
@@ -205,10 +218,13 @@
      *
      * @param fd the fd of socket to switch back to normal.
      */
-    // TODO : make this private.
-    public static void switchOutOfRepairMode(@NonNull final FileDescriptor fd)
-            throws ErrnoException {
-        Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR, TCP_REPAIR_OFF);
+    private static void switchOutOfRepairMode(@NonNull final FileDescriptor fd) {
+        try {
+            Os.setsockoptInt(fd, IPPROTO_TCP, TCP_REPAIR, TCP_REPAIR_OFF);
+        } catch (ErrnoException e) {
+            Log.e(TAG, "Cannot switch socket out of repair mode", e);
+            // Well, there is not much to do here to recover
+        }
     }
 
     /**
@@ -262,17 +278,12 @@
             mListeners.remove(slot);
         }
         mFdHandlerQueue.removeOnFileDescriptorEventListener(fd);
-        try {
-            if (DBG) Log.d(TAG, "Moving socket out of repair mode for stop : " + fd);
-            switchOutOfRepairMode(fd);
-        } catch (ErrnoException e) {
-            Log.e(TAG, "Cannot switch socket out of repair mode", e);
-            // Well, there is not much to do here to recover
-        }
+        if (DBG) Log.d(TAG, "Moving socket out of repair mode for stop : " + fd);
+        switchOutOfRepairMode(fd);
     }
 
-    private static InetAddress getAddress(InetSocketAddress inetAddr) {
-        return inetAddr.getAddress();
+    private static byte [] getAddress(InetSocketAddress inetAddr) {
+        return inetAddr.getAddress().getAddress();
     }
 
     private static int getPort(InetSocketAddress inetAddr) {
diff --git a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java
index 1f2dd27..372ffcd 100644
--- a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java
+++ b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java
@@ -21,12 +21,9 @@
 import static org.junit.Assert.fail;
 
 import android.net.SocketKeepalive.InvalidPacketException;
-import android.net.TcpKeepalivePacketData.TcpSocketInfo;
 
 import com.android.internal.util.TestUtils;
 
-import libcore.net.InetAddressUtils;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -37,14 +34,14 @@
 
 @RunWith(JUnit4.class)
 public final class TcpKeepalivePacketDataTest {
+    private static final byte[] IPV4_KEEPALIVE_SRC_ADDR = {10, 0, 0, 1};
+    private static final byte[] IPV4_KEEPALIVE_DST_ADDR = {10, 0, 0, 5};
 
     @Before
     public void setUp() {}
 
     @Test
-    public void testV4TcpKeepalivePacket() {
-        final InetAddress srcAddr = InetAddressUtils.parseNumericAddress("192.168.0.1");
-        final InetAddress dstAddr = InetAddressUtils.parseNumericAddress("192.168.0.10");
+    public void testV4TcpKeepalivePacket() throws Exception {
         final int srcPort = 1234;
         final int dstPort = 4321;
         final int seq = 0x11111111;
@@ -52,20 +49,28 @@
         final int wnd = 8000;
         final int wndScale = 2;
         TcpKeepalivePacketData resultData = null;
-        TcpSocketInfo testInfo = new TcpSocketInfo(
-                srcAddr, srcPort, dstAddr, dstPort, seq, ack, wnd, wndScale);
+        final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable();
+        testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR;
+        testInfo.srcPort = srcPort;
+        testInfo.dstAddress = IPV4_KEEPALIVE_DST_ADDR;
+        testInfo.dstPort = dstPort;
+        testInfo.seq = seq;
+        testInfo.ack = ack;
+        testInfo.rcvWnd = wnd;
+        testInfo.rcvWndScale = wndScale;
         try {
             resultData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo);
         } catch (InvalidPacketException e) {
             fail("InvalidPacketException: " + e);
         }
 
-        assertEquals(testInfo.srcAddress, resultData.srcAddress);
-        assertEquals(testInfo.dstAddress, resultData.dstAddress);
+        assertEquals(InetAddress.getByAddress(testInfo.srcAddress), resultData.srcAddress);
+        assertEquals(InetAddress.getByAddress(testInfo.dstAddress), resultData.dstAddress);
         assertEquals(testInfo.srcPort, resultData.srcPort);
         assertEquals(testInfo.dstPort, resultData.dstPort);
         assertEquals(testInfo.seq, resultData.tcpSeq);
         assertEquals(testInfo.ack, resultData.tcpAck);
+        assertEquals(testInfo.rcvWnd, resultData.tcpWnd);
         assertEquals(testInfo.rcvWndScale, resultData.tcpWndScale);
 
         TestUtils.assertParcelingIsLossless(resultData, TcpKeepalivePacketData.CREATOR);
@@ -78,11 +83,11 @@
         byte[] ip = new byte[4];
         buf = ByteBuffer.wrap(packet, 12, 4);
         buf.get(ip);
-        assertArrayEquals(ip, srcAddr.getAddress());
+        assertArrayEquals(ip, IPV4_KEEPALIVE_SRC_ADDR);
         // Destination IP address.
         buf = ByteBuffer.wrap(packet, 16, 4);
         buf.get(ip);
-        assertArrayEquals(ip, dstAddr.getAddress());
+        assertArrayEquals(ip, IPV4_KEEPALIVE_DST_ADDR);
 
         buf = ByteBuffer.wrap(packet, 20, 12);
         // Source port.
@@ -102,25 +107,32 @@
 
     @Test
     public void testParcel() throws Exception {
-        final InetAddress srcAddr = InetAddresses.parseNumericAddress("192.168.0.1");
-        final InetAddress dstAddr = InetAddresses.parseNumericAddress("192.168.0.10");
         final int srcPort = 1234;
         final int dstPort = 4321;
         final int sequence = 0x11111111;
         final int ack = 0x22222222;
         final int wnd = 48_000;
         final int wndScale = 2;
+        final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable();
+        testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR;
+        testInfo.srcPort = srcPort;
+        testInfo.dstAddress = IPV4_KEEPALIVE_DST_ADDR;
+        testInfo.dstPort = dstPort;
+        testInfo.seq = sequence;
+        testInfo.ack = ack;
+        testInfo.rcvWnd = wnd;
+        testInfo.rcvWndScale = wndScale;
         TcpKeepalivePacketData testData = null;
         TcpKeepalivePacketDataParcelable resultData = null;
-        TcpSocketInfo testInfo = new TcpSocketInfo(
-                srcAddr, srcPort, dstAddr, dstPort, sequence, ack, wnd, wndScale);
         testData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo);
         resultData = testData.toStableParcelable();
-        assertArrayEquals(resultData.srcAddress, srcAddr.getAddress());
-        assertArrayEquals(resultData.dstAddress, dstAddr.getAddress());
+        assertArrayEquals(resultData.srcAddress, IPV4_KEEPALIVE_SRC_ADDR);
+        assertArrayEquals(resultData.dstAddress, IPV4_KEEPALIVE_DST_ADDR);
         assertEquals(resultData.srcPort, srcPort);
         assertEquals(resultData.dstPort, dstPort);
         assertEquals(resultData.seq, sequence);
         assertEquals(resultData.ack, ack);
+        assertEquals(resultData.rcvWnd, wnd);
+        assertEquals(resultData.rcvWndScale, wndScale);
     }
 }
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 3efdfd9..d3616aa 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -495,7 +495,7 @@
             try {
                 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected();
                 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
-                doAnswer(validateAnswer).when(mNetworkMonitor).notifyAcceptPartialConnectivity();
+                doAnswer(validateAnswer).when(mNetworkMonitor).setAcceptPartialConnectivity();
             } catch (RemoteException e) {
                 fail(e.getMessage());
             }
@@ -2550,7 +2550,7 @@
         verifyActiveNetwork(TRANSPORT_CELLULAR);
     }
 
-    // TODO: deflake and re-enable
+    // TODO(b/128426024): deflake and re-enable
     // @Test
     public void testPartialConnectivity() {
         // Register network callback.
@@ -2585,7 +2585,7 @@
         waitForIdle();
         try {
             verify(mWiFiNetworkAgent.mNetworkMonitor,
-                    timeout(TIMEOUT_MS).times(1)).notifyAcceptPartialConnectivity();
+                    timeout(TIMEOUT_MS).times(1)).setAcceptPartialConnectivity();
         } catch (RemoteException e) {
             fail(e.getMessage());
         }
@@ -2641,7 +2641,7 @@
         waitForIdle();
         try {
             verify(mWiFiNetworkAgent.mNetworkMonitor,
-                    timeout(TIMEOUT_MS).times(1)).notifyAcceptPartialConnectivity();
+                    timeout(TIMEOUT_MS).times(1)).setAcceptPartialConnectivity();
         } catch (RemoteException e) {
             fail(e.getMessage());
         }
diff --git a/tests/net/java/com/android/server/NetworkManagementServiceTest.java b/tests/net/java/com/android/server/NetworkManagementServiceTest.java
index 6fb3225..968b307 100644
--- a/tests/net/java/com/android/server/NetworkManagementServiceTest.java
+++ b/tests/net/java/com/android/server/NetworkManagementServiceTest.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
@@ -23,11 +24,11 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.net.INetd;
+import android.net.INetdUnsolicitedEventListener;
 import android.net.LinkAddress;
-import android.net.LocalServerSocket;
-import android.net.LocalSocket;
 import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.IBinder;
@@ -43,12 +44,11 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.io.IOException;
-import java.io.OutputStream;
-
 /**
  * Tests for {@link NetworkManagementService}.
  */
@@ -56,16 +56,16 @@
 @SmallTest
 public class NetworkManagementServiceTest {
 
-    private static final String SOCKET_NAME = "__test__NetworkManagementServiceTest";
     private NetworkManagementService mNMService;
-    private LocalServerSocket mServerSocket;
-    private LocalSocket mSocket;
-    private OutputStream mOutputStream;
 
     @Mock private Context mContext;
     @Mock private IBatteryStats.Stub mBatteryStatsService;
     @Mock private INetd.Stub mNetdService;
 
+    @NonNull
+    @Captor
+    private ArgumentCaptor<INetdUnsolicitedEventListener> mUnsolListenerCaptor;
+
     private final SystemServices mServices = new SystemServices() {
         @Override
         public IBinder getService(String name) {
@@ -88,32 +88,15 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-
-        // Set up a sheltered test environment.
-        mServerSocket = new LocalServerSocket(SOCKET_NAME);
-
+        doNothing().when(mNetdService)
+                .registerUnsolicitedEventListener(mUnsolListenerCaptor.capture());
         // Start the service and wait until it connects to our socket.
-        mNMService = NetworkManagementService.create(mContext, SOCKET_NAME, mServices);
-        mSocket = mServerSocket.accept();
-        mOutputStream = mSocket.getOutputStream();
+        mNMService = NetworkManagementService.create(mContext, mServices);
     }
 
     @After
     public void tearDown() throws Exception {
         mNMService.shutdown();
-        // Once NetworkManagementService#shutdown() actually does something and shutdowns
-        // the underlying NativeDaemonConnector, the block below should be uncommented.
-        // if (mOutputStream != null) mOutputStream.close();
-        // if (mSocket != null) mSocket.close();
-        // if (mServerSocket != null) mServerSocket.close();
-    }
-
-    /**
-     * Sends a message on the netd socket and gives the events some time to make it back.
-     */
-    private void sendMessage(String message) throws IOException {
-        // Strings are null-terminated, so add "\0" at the end.
-        mOutputStream.write((message + "\0").getBytes());
     }
 
     private static <T> T expectSoon(T mock) {
@@ -131,125 +114,78 @@
 
         // Forget everything that happened to the mock so far, so we can explicitly verify
         // everything that happens and does not happen to it from now on.
-        reset(observer);
 
-        // Now send NetworkManagementService messages and ensure that the observer methods are
-        // called. After every valid message we expect a callback soon after; to ensure that
+        INetdUnsolicitedEventListener unsolListener = mUnsolListenerCaptor.getValue();
+        reset(observer);
+        // Now call unsolListener methods and ensure that the observer methods are
+        // called. After every method we expect a callback soon after; to ensure that
         // invalid messages don't cause any callbacks, we call verifyNoMoreInteractions at the end.
 
         /**
          * Interface changes.
          */
-        sendMessage("600 Iface added rmnet12");
+        unsolListener.onInterfaceAdded("rmnet12");
         expectSoon(observer).interfaceAdded("rmnet12");
 
-        sendMessage("600 Iface removed eth1");
+        unsolListener.onInterfaceRemoved("eth1");
         expectSoon(observer).interfaceRemoved("eth1");
 
-        sendMessage("607 Iface removed eth1");
-        // Invalid code.
-
-        sendMessage("600 Iface borked lo down");
-        // Invalid event.
-
-        sendMessage("600 Iface changed clat4 up again");
-        // Extra tokens.
-
-        sendMessage("600 Iface changed clat4 up");
+        unsolListener.onInterfaceChanged("clat4", true);
         expectSoon(observer).interfaceStatusChanged("clat4", true);
 
-        sendMessage("600 Iface linkstate rmnet0 down");
+        unsolListener.onInterfaceLinkStateChanged("rmnet0", false);
         expectSoon(observer).interfaceLinkStateChanged("rmnet0", false);
 
-        sendMessage("600 IFACE linkstate clat4 up");
-        // Invalid group.
-
         /**
          * Bandwidth control events.
          */
-        sendMessage("601 limit alert data rmnet_usb0");
+        unsolListener.onQuotaLimitReached("data", "rmnet_usb0");
         expectSoon(observer).limitReached("data", "rmnet_usb0");
 
-        sendMessage("601 invalid alert data rmnet0");
-        // Invalid group.
-
-        sendMessage("601 limit increased data rmnet0");
-        // Invalid event.
-
-
         /**
          * Interface class activity.
          */
-
-        sendMessage("613 IfaceClass active 1 1234 10012");
+        unsolListener.onInterfaceClassActivityChanged(true, 1, 1234, 0);
         expectSoon(observer).interfaceClassDataActivityChanged("1", true, 1234);
 
-        sendMessage("613 IfaceClass idle 9 5678");
+        unsolListener.onInterfaceClassActivityChanged(false, 9, 5678, 0);
         expectSoon(observer).interfaceClassDataActivityChanged("9", false, 5678);
 
-        sendMessage("613 IfaceClass reallyactive 9 4321");
+        unsolListener.onInterfaceClassActivityChanged(false, 9, 4321, 0);
         expectSoon(observer).interfaceClassDataActivityChanged("9", false, 4321);
 
-        sendMessage("613 InterfaceClass reallyactive 1");
-        // Invalid group.
-
-
         /**
          * IP address changes.
          */
-        sendMessage("614 Address updated fe80::1/64 wlan0 128 253");
+        unsolListener.onInterfaceAddressUpdated("fe80::1/64", "wlan0", 128, 253);
         expectSoon(observer).addressUpdated("wlan0", new LinkAddress("fe80::1/64", 128, 253));
 
-        // There is no "added", so we take this as "removed".
-        sendMessage("614 Address added fe80::1/64 wlan0 128 253");
+        unsolListener.onInterfaceAddressRemoved("fe80::1/64", "wlan0", 128, 253);
         expectSoon(observer).addressRemoved("wlan0", new LinkAddress("fe80::1/64", 128, 253));
 
-        sendMessage("614 Address removed 2001:db8::1/64 wlan0 1 0");
+        unsolListener.onInterfaceAddressRemoved("2001:db8::1/64", "wlan0", 1, 0);
         expectSoon(observer).addressRemoved("wlan0", new LinkAddress("2001:db8::1/64", 1, 0));
 
-        sendMessage("614 Address removed 2001:db8::1/64 wlan0 1");
-        // Not enough arguments.
-
-        sendMessage("666 Address removed 2001:db8::1/64 wlan0 1 0");
-        // Invalid code.
-
-
         /**
          * DNS information broadcasts.
          */
-        sendMessage("615 DnsInfo servers rmnet_usb0 3600 2001:db8::1");
+        unsolListener.onInterfaceDnsServerInfo("rmnet_usb0", 3600, new String[]{"2001:db8::1"});
         expectSoon(observer).interfaceDnsServerInfo("rmnet_usb0", 3600,
                 new String[]{"2001:db8::1"});
 
-        sendMessage("615 DnsInfo servers wlan0 14400 2001:db8::1,2001:db8::2");
+        unsolListener.onInterfaceDnsServerInfo("wlan0", 14400,
+                new String[]{"2001:db8::1", "2001:db8::2"});
         expectSoon(observer).interfaceDnsServerInfo("wlan0", 14400,
                 new String[]{"2001:db8::1", "2001:db8::2"});
 
         // We don't check for negative lifetimes, only for parse errors.
-        sendMessage("615 DnsInfo servers wlan0 -3600 ::1");
+        unsolListener.onInterfaceDnsServerInfo("wlan0", -3600, new String[]{"::1"});
         expectSoon(observer).interfaceDnsServerInfo("wlan0", -3600,
                 new String[]{"::1"});
 
-        sendMessage("615 DnsInfo servers wlan0 SIXHUNDRED ::1");
-        // Non-numeric lifetime.
-
-        sendMessage("615 DnsInfo servers wlan0 2001:db8::1");
-        // Missing lifetime.
-
-        sendMessage("615 DnsInfo servers wlan0 3600");
-        // No servers.
-
-        sendMessage("615 DnsInfo servers 3600 wlan0 2001:db8::1,2001:db8::2");
-        // Non-numeric lifetime.
-
-        sendMessage("615 DnsInfo wlan0 7200 2001:db8::1,2001:db8::2");
-        // Invalid tokens.
-
-        sendMessage("666 DnsInfo servers wlan0 5400 2001:db8::1");
-        // Invalid code.
-
         // No syntax checking on the addresses.
-        sendMessage("615 DnsInfo servers wlan0 600 ,::,,foo,::1,");
+        unsolListener.onInterfaceDnsServerInfo("wlan0", 600,
+                new String[]{"", "::", "", "foo", "::1"});
         expectSoon(observer).interfaceDnsServerInfo("wlan0", 600,
                 new String[]{"", "::", "", "foo", "::1"});