Merge "[KA02] internal cleanup and refactor for SocketKeepalive" am: 292da961e6

am: 839c99be82

Change-Id: I242fdacdd70729367f60da80a1a27d8f5a08dff6
This commit is contained in:
Chalard Jean
2019-02-05 10:39:31 -08:00
committed by android-build-merger
8 changed files with 177 additions and 120 deletions

View File

@@ -1816,7 +1816,7 @@ public class ConnectivityManager {
@Override @Override
public void handleMessage(Message message) { public void handleMessage(Message message) {
switch (message.what) { switch (message.what) {
case NetworkAgent.EVENT_PACKET_KEEPALIVE: case NetworkAgent.EVENT_SOCKET_KEEPALIVE:
int error = message.arg2; int error = message.arg2;
try { try {
if (error == SUCCESS) { if (error == SUCCESS) {

View File

@@ -16,22 +16,20 @@
package android.net; package android.net;
import static android.net.ConnectivityManager.PacketKeepalive.*; import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
import static android.net.SocketKeepalive.ERROR_INVALID_PORT;
import android.net.SocketKeepalive.InvalidPacketException;
import android.net.util.IpUtils; import android.net.util.IpUtils;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import android.system.OsConstants;
import android.util.Log; import android.util.Log;
import java.net.Inet4Address;
import java.net.InetAddress; import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/** /**
* Represents the actual packets that are sent by the * Represents the actual packets that are sent by the
* {@link android.net.ConnectivityManager.PacketKeepalive} API. * {@link android.net.SocketKeepalive} API.
* *
* @hide * @hide
*/ */
@@ -53,8 +51,8 @@ public class KeepalivePacketData implements Parcelable {
/** Packet data. A raw byte string of packet data, not including the link-layer header. */ /** Packet data. A raw byte string of packet data, not including the link-layer header. */
private final byte[] mPacket; private final byte[] mPacket;
private static final int IPV4_HEADER_LENGTH = 20; protected static final int IPV4_HEADER_LENGTH = 20;
private static final int UDP_HEADER_LENGTH = 8; protected static final int UDP_HEADER_LENGTH = 8;
// This should only be constructed via static factory methods, such as // This should only be constructed via static factory methods, such as
// nattKeepalivePacket // nattKeepalivePacket
@@ -80,53 +78,10 @@ public class KeepalivePacketData implements Parcelable {
} }
} }
public static class InvalidPacketException extends Exception {
public final int error;
public InvalidPacketException(int error) {
this.error = error;
}
}
public byte[] getPacket() { public byte[] getPacket() {
return mPacket.clone(); return mPacket.clone();
} }
public static KeepalivePacketData nattKeepalivePacket(
InetAddress srcAddress, int srcPort, InetAddress dstAddress, int dstPort)
throws InvalidPacketException {
if (!(srcAddress instanceof Inet4Address) || !(dstAddress instanceof Inet4Address)) {
throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS);
}
if (dstPort != NATT_PORT) {
throw new InvalidPacketException(ERROR_INVALID_PORT);
}
int length = IPV4_HEADER_LENGTH + UDP_HEADER_LENGTH + 1;
ByteBuffer buf = ByteBuffer.allocate(length);
buf.order(ByteOrder.BIG_ENDIAN);
buf.putShort((short) 0x4500); // IP version and TOS
buf.putShort((short) length);
buf.putInt(0); // ID, flags, offset
buf.put((byte) 64); // TTL
buf.put((byte) OsConstants.IPPROTO_UDP);
int ipChecksumOffset = buf.position();
buf.putShort((short) 0); // IP checksum
buf.put(srcAddress.getAddress());
buf.put(dstAddress.getAddress());
buf.putShort((short) srcPort);
buf.putShort((short) dstPort);
buf.putShort((short) (length - 20)); // UDP length
int udpChecksumOffset = buf.position();
buf.putShort((short) 0); // UDP checksum
buf.put((byte) 0xff); // NAT-T keepalive
buf.putShort(ipChecksumOffset, IpUtils.ipChecksum(buf, 0));
buf.putShort(udpChecksumOffset, IpUtils.udpChecksum(buf, 0, IPV4_HEADER_LENGTH));
return new KeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, buf.array());
}
/* Parcelable Implementation */ /* Parcelable Implementation */
public int describeContents() { public int describeContents() {
return 0; return 0;

View File

@@ -0,0 +1,77 @@
/*
* Copyright (C) 2019 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 android.net;
import android.net.SocketKeepalive.InvalidPacketException;
import android.net.util.IpUtils;
import android.system.OsConstants;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/** @hide */
public final class NattKeepalivePacketData extends KeepalivePacketData {
// This should only be constructed via static factory methods, such as
// nattKeepalivePacket
private NattKeepalivePacketData(InetAddress srcAddress, int srcPort,
InetAddress dstAddress, int dstPort, byte[] data) throws
InvalidPacketException {
super(srcAddress, srcPort, dstAddress, dstPort, data);
}
/**
* Factory method to create Nat-T keepalive packet structure.
*/
public static NattKeepalivePacketData nattKeepalivePacket(
InetAddress srcAddress, int srcPort, InetAddress dstAddress, int dstPort)
throws InvalidPacketException {
if (!(srcAddress instanceof Inet4Address) || !(dstAddress instanceof Inet4Address)) {
throw new InvalidPacketException(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
}
if (dstPort != NattSocketKeepalive.NATT_PORT) {
throw new InvalidPacketException(SocketKeepalive.ERROR_INVALID_PORT);
}
int length = IPV4_HEADER_LENGTH + UDP_HEADER_LENGTH + 1;
ByteBuffer buf = ByteBuffer.allocate(length);
buf.order(ByteOrder.BIG_ENDIAN);
buf.putShort((short) 0x4500); // IP version and TOS
buf.putShort((short) length);
buf.putInt(0); // ID, flags, offset
buf.put((byte) 64); // TTL
buf.put((byte) OsConstants.IPPROTO_UDP);
int ipChecksumOffset = buf.position();
buf.putShort((short) 0); // IP checksum
buf.put(srcAddress.getAddress());
buf.put(dstAddress.getAddress());
buf.putShort((short) srcPort);
buf.putShort((short) dstPort);
buf.putShort((short) (length - 20)); // UDP length
int udpChecksumOffset = buf.position();
buf.putShort((short) 0); // UDP checksum
buf.put((byte) 0xff); // NAT-T keepalive
buf.putShort(ipChecksumOffset, IpUtils.ipChecksum(buf, 0));
buf.putShort(udpChecksumOffset, IpUtils.udpChecksum(buf, 0, IPV4_HEADER_LENGTH));
return new NattKeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, buf.array());
}
}

View File

@@ -18,7 +18,6 @@ package android.net;
import android.annotation.UnsupportedAppUsage; import android.annotation.UnsupportedAppUsage;
import android.content.Context; import android.content.Context;
import android.net.ConnectivityManager.PacketKeepalive;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
@@ -154,7 +153,7 @@ public abstract class NetworkAgent extends Handler {
* *
* Also used internally by ConnectivityService / KeepaliveTracker, with different semantics. * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics.
*/ */
public static final int CMD_START_PACKET_KEEPALIVE = BASE + 11; public static final int CMD_START_SOCKET_KEEPALIVE = BASE + 11;
/** /**
* Requests that the specified keepalive packet be stopped. * Requests that the specified keepalive packet be stopped.
@@ -163,20 +162,20 @@ public abstract class NetworkAgent extends Handler {
* *
* Also used internally by ConnectivityService / KeepaliveTracker, with different semantics. * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics.
*/ */
public static final int CMD_STOP_PACKET_KEEPALIVE = BASE + 12; public static final int CMD_STOP_SOCKET_KEEPALIVE = BASE + 12;
/** /**
* Sent by the NetworkAgent to ConnectivityService to provide status on a packet keepalive * Sent by the NetworkAgent to ConnectivityService to provide status on a socket keepalive
* request. This may either be the reply to a CMD_START_PACKET_KEEPALIVE, or an asynchronous * request. This may either be the reply to a CMD_START_SOCKET_KEEPALIVE, or an asynchronous
* error notification. * error notification.
* *
* This is also sent by KeepaliveTracker to the app's ConnectivityManager.PacketKeepalive to * This is also sent by KeepaliveTracker to the app's {@link SocketKeepalive},
* so that the app's PacketKeepaliveCallback methods can be called. * so that the app's {@link SocketKeepalive.Callback} methods can be called.
* *
* arg1 = slot number of the keepalive * arg1 = slot number of the keepalive
* arg2 = error code * arg2 = error code
*/ */
public static final int EVENT_PACKET_KEEPALIVE = BASE + 13; public static final int EVENT_SOCKET_KEEPALIVE = BASE + 13;
/** /**
* Sent by ConnectivityService to inform this network transport of signal strength thresholds * Sent by ConnectivityService to inform this network transport of signal strength thresholds
@@ -288,12 +287,12 @@ public abstract class NetworkAgent extends Handler {
saveAcceptUnvalidated(msg.arg1 != 0); saveAcceptUnvalidated(msg.arg1 != 0);
break; break;
} }
case CMD_START_PACKET_KEEPALIVE: { case CMD_START_SOCKET_KEEPALIVE: {
startPacketKeepalive(msg); startSocketKeepalive(msg);
break; break;
} }
case CMD_STOP_PACKET_KEEPALIVE: { case CMD_STOP_SOCKET_KEEPALIVE: {
stopPacketKeepalive(msg); stopSocketKeepalive(msg);
break; break;
} }
@@ -443,22 +442,22 @@ public abstract class NetworkAgent extends Handler {
/** /**
* Requests that the network hardware send the specified packet at the specified interval. * Requests that the network hardware send the specified packet at the specified interval.
*/ */
protected void startPacketKeepalive(Message msg) { protected void startSocketKeepalive(Message msg) {
onPacketKeepaliveEvent(msg.arg1, PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
} }
/** /**
* Requests that the network hardware send the specified packet at the specified interval. * Requests that the network hardware stops sending keepalive packets.
*/ */
protected void stopPacketKeepalive(Message msg) { protected void stopSocketKeepalive(Message msg) {
onPacketKeepaliveEvent(msg.arg1, PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED); onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
} }
/** /**
* Called by the network when a packet keepalive event occurs. * Called by the network when a socket keepalive event occurs.
*/ */
public void onPacketKeepaliveEvent(int slot, int reason) { public void onSocketKeepaliveEvent(int slot, int reason) {
queueOrSendMessage(EVENT_PACKET_KEEPALIVE, slot, reason); queueOrSendMessage(EVENT_SOCKET_KEEPALIVE, slot, reason);
} }
/** /**

View File

@@ -109,6 +109,18 @@ public abstract class SocketKeepalive implements AutoCloseable {
**/ **/
public static final int MAX_INTERVAL_SEC = 3600; public static final int MAX_INTERVAL_SEC = 3600;
/**
* This packet is invalid.
* See the error code for details.
* @hide
*/
public static class InvalidPacketException extends Exception {
public final int error;
public InvalidPacketException(int error) {
this.error = error;
}
}
@NonNull final IConnectivityManager mService; @NonNull final IConnectivityManager mService;
@NonNull final Network mNetwork; @NonNull final Network mNetwork;
@NonNull private final Executor mExecutor; @NonNull private final Executor mExecutor;
@@ -135,7 +147,7 @@ public abstract class SocketKeepalive implements AutoCloseable {
@Override @Override
public void handleMessage(Message message) { public void handleMessage(Message message) {
switch (message.what) { switch (message.what) {
case NetworkAgent.EVENT_PACKET_KEEPALIVE: case NetworkAgent.EVENT_SOCKET_KEEPALIVE:
final int status = message.arg2; final int status = message.arg2;
try { try {
if (status == SUCCESS) { if (status == SUCCESS) {

View File

@@ -60,7 +60,6 @@ import android.content.res.Configuration;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.net.ConnectionInfo; import android.net.ConnectionInfo;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.ConnectivityManager.PacketKeepalive;
import android.net.IConnectivityManager; import android.net.IConnectivityManager;
import android.net.IIpConnectivityMetrics; import android.net.IIpConnectivityMetrics;
import android.net.INetd; import android.net.INetd;
@@ -93,6 +92,7 @@ import android.net.NetworkWatchlistManager;
import android.net.PrivateDnsConfigParcel; import android.net.PrivateDnsConfigParcel;
import android.net.ProxyInfo; import android.net.ProxyInfo;
import android.net.RouteInfo; import android.net.RouteInfo;
import android.net.SocketKeepalive;
import android.net.UidRange; import android.net.UidRange;
import android.net.Uri; import android.net.Uri;
import android.net.VpnService; import android.net.VpnService;
@@ -2487,8 +2487,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
nai.networkMisc.acceptUnvalidated = msg.arg1 == 1; nai.networkMisc.acceptUnvalidated = msg.arg1 == 1;
break; break;
} }
case NetworkAgent.EVENT_PACKET_KEEPALIVE: { case NetworkAgent.EVENT_SOCKET_KEEPALIVE: {
mKeepaliveTracker.handleEventPacketKeepalive(nai, msg); mKeepaliveTracker.handleEventSocketKeepalive(nai, msg);
break; break;
} }
} }
@@ -2853,8 +2853,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// sending all CALLBACK_LOST messages (for requests, not listens) at the end // sending all CALLBACK_LOST messages (for requests, not listens) at the end
// of rematchAllNetworksAndRequests // of rematchAllNetworksAndRequests
notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOST); notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOST);
mKeepaliveTracker.handleStopAllKeepalives(nai, mKeepaliveTracker.handleStopAllKeepalives(nai, SocketKeepalive.ERROR_INVALID_NETWORK);
ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK);
for (String iface : nai.linkProperties.getAllInterfaceNames()) { for (String iface : nai.linkProperties.getAllInterfaceNames()) {
// Disable wakeup packet monitoring for each interface. // Disable wakeup packet monitoring for each interface.
wakeupModifyInterface(iface, nai.networkCapabilities, false); wakeupModifyInterface(iface, nai.networkCapabilities, false);
@@ -3446,12 +3445,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
break; break;
} }
// Sent by KeepaliveTracker to process an app request on the state machine thread. // Sent by KeepaliveTracker to process an app request on the state machine thread.
case NetworkAgent.CMD_START_PACKET_KEEPALIVE: { case NetworkAgent.CMD_START_SOCKET_KEEPALIVE: {
mKeepaliveTracker.handleStartKeepalive(msg); mKeepaliveTracker.handleStartKeepalive(msg);
break; break;
} }
// Sent by KeepaliveTracker to process an app request on the state machine thread. // Sent by KeepaliveTracker to process an app request on the state machine thread.
case NetworkAgent.CMD_STOP_PACKET_KEEPALIVE: { case NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE: {
NetworkAgentInfo nai = getNetworkAgentInfoForNetwork((Network) msg.obj); NetworkAgentInfo nai = getNetworkAgentInfoForNetwork((Network) msg.obj);
int slot = msg.arg1; int slot = msg.arg1;
int reason = msg.arg2; int reason = msg.arg2;
@@ -6315,7 +6314,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
mKeepaliveTracker.startNattKeepalive( mKeepaliveTracker.startNattKeepalive(
getNetworkAgentInfoForNetwork(network), getNetworkAgentInfoForNetwork(network),
intervalSeconds, messenger, binder, intervalSeconds, messenger, binder,
srcAddr, srcPort, dstAddr, ConnectivityManager.PacketKeepalive.NATT_PORT); srcAddr, srcPort, dstAddr, NattSocketKeepalive.NATT_PORT);
} }
@Override @Override
@@ -6332,7 +6331,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
@Override @Override
public void stopKeepalive(Network network, int slot) { public void stopKeepalive(Network network, int slot) {
mHandler.sendMessage(mHandler.obtainMessage( mHandler.sendMessage(mHandler.obtainMessage(
NetworkAgent.CMD_STOP_PACKET_KEEPALIVE, slot, PacketKeepalive.SUCCESS, network)); NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE, slot, SocketKeepalive.SUCCESS, network));
} }
@Override @Override

View File

@@ -16,26 +16,27 @@
package com.android.server.connectivity; package com.android.server.connectivity;
// TODO: Clean up imports and remove references of PacketKeepalive constants. import static android.net.NattSocketKeepalive.NATT_PORT;
import static android.net.NetworkAgent.CMD_START_SOCKET_KEEPALIVE;
import static android.net.ConnectivityManager.PacketKeepalive.ERROR_INVALID_INTERVAL; import static android.net.NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE;
import static android.net.ConnectivityManager.PacketKeepalive.ERROR_INVALID_IP_ADDRESS; import static android.net.NetworkAgent.EVENT_SOCKET_KEEPALIVE;
import static android.net.ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK; import static android.net.SocketKeepalive.BINDER_DIED;
import static android.net.ConnectivityManager.PacketKeepalive.MIN_INTERVAL; import static android.net.SocketKeepalive.ERROR_INVALID_INTERVAL;
import static android.net.ConnectivityManager.PacketKeepalive.NATT_PORT; import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
import static android.net.ConnectivityManager.PacketKeepalive.NO_KEEPALIVE; import static android.net.SocketKeepalive.ERROR_INVALID_NETWORK;
import static android.net.ConnectivityManager.PacketKeepalive.SUCCESS;
import static android.net.NetworkAgent.CMD_START_PACKET_KEEPALIVE;
import static android.net.NetworkAgent.CMD_STOP_PACKET_KEEPALIVE;
import static android.net.NetworkAgent.EVENT_PACKET_KEEPALIVE;
import static android.net.SocketKeepalive.ERROR_INVALID_SOCKET; import static android.net.SocketKeepalive.ERROR_INVALID_SOCKET;
import static android.net.SocketKeepalive.MAX_INTERVAL_SEC;
import static android.net.SocketKeepalive.MIN_INTERVAL_SEC;
import static android.net.SocketKeepalive.NO_KEEPALIVE;
import static android.net.SocketKeepalive.SUCCESS;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.net.ConnectivityManager.PacketKeepalive;
import android.net.KeepalivePacketData; import android.net.KeepalivePacketData;
import android.net.NattKeepalivePacketData;
import android.net.NetworkAgent; import android.net.NetworkAgent;
import android.net.NetworkUtils; import android.net.NetworkUtils;
import android.net.SocketKeepalive.InvalidPacketException;
import android.net.util.IpUtils; import android.net.util.IpUtils;
import android.os.Binder; import android.os.Binder;
import android.os.Handler; import android.os.Handler;
@@ -60,7 +61,7 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
/** /**
* Manages packet keepalive requests. * Manages socket keepalive requests.
* *
* Provides methods to stop and start keepalive requests, and keeps track of keepalives across all * Provides methods to stop and start keepalive requests, and keeps track of keepalives across all
* networks. This class is tightly coupled to ConnectivityService. It is not thread-safe and its * networks. This class is tightly coupled to ConnectivityService. It is not thread-safe and its
@@ -83,13 +84,13 @@ public class KeepaliveTracker {
} }
/** /**
* Tracks information about a packet keepalive. * Tracks information about a socket keepalive.
* *
* All information about this keepalive is known at construction time except the slot number, * All information about this keepalive is known at construction time except the slot number,
* which is only returned when the hardware has successfully started the keepalive. * which is only returned when the hardware has successfully started the keepalive.
*/ */
class KeepaliveInfo implements IBinder.DeathRecipient { class KeepaliveInfo implements IBinder.DeathRecipient {
// Bookkeping data. // Bookkeeping data.
private final Messenger mMessenger; private final Messenger mMessenger;
private final IBinder mBinder; private final IBinder mBinder;
private final int mUid; private final int mUid;
@@ -98,7 +99,7 @@ public class KeepaliveTracker {
/** Keepalive slot. A small integer that identifies this keepalive among the ones handled /** Keepalive slot. A small integer that identifies this keepalive among the ones handled
* by this network. */ * by this network. */
private int mSlot = PacketKeepalive.NO_KEEPALIVE; private int mSlot = NO_KEEPALIVE;
// Packet data. // Packet data.
private final KeepalivePacketData mPacket; private final KeepalivePacketData mPacket;
@@ -144,7 +145,7 @@ public class KeepaliveTracker {
.toString(); .toString();
} }
/** Sends a message back to the application via its PacketKeepalive.Callback. */ /** Sends a message back to the application via its SocketKeepalive.Callback. */
void notifyMessenger(int slot, int err) { void notifyMessenger(int slot, int err) {
KeepaliveTracker.this.notifyMessenger(mMessenger, slot, err); KeepaliveTracker.this.notifyMessenger(mMessenger, slot, err);
} }
@@ -153,8 +154,8 @@ public class KeepaliveTracker {
public void binderDied() { public void binderDied() {
// Not called from ConnectivityService handler thread, so send it a message. // Not called from ConnectivityService handler thread, so send it a message.
mConnectivityServiceHandler.obtainMessage( mConnectivityServiceHandler.obtainMessage(
NetworkAgent.CMD_STOP_PACKET_KEEPALIVE, NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE,
mSlot, PacketKeepalive.BINDER_DIED, mNai.network).sendToTarget(); mSlot, BINDER_DIED, mNai.network).sendToTarget();
} }
void unlinkDeathRecipient() { void unlinkDeathRecipient() {
@@ -181,7 +182,10 @@ public class KeepaliveTracker {
} }
private int checkInterval() { private int checkInterval() {
return mInterval >= MIN_INTERVAL ? SUCCESS : ERROR_INVALID_INTERVAL; if (mInterval < MIN_INTERVAL_SEC || mInterval > MAX_INTERVAL_SEC) {
return ERROR_INVALID_INTERVAL;
}
return SUCCESS;
} }
private int isValid() { private int isValid() {
@@ -198,7 +202,7 @@ public class KeepaliveTracker {
int error = isValid(); int error = isValid();
if (error == SUCCESS) { if (error == SUCCESS) {
Log.d(TAG, "Starting keepalive " + mSlot + " on " + mNai.name()); Log.d(TAG, "Starting keepalive " + mSlot + " on " + mNai.name());
mNai.asyncChannel.sendMessage(CMD_START_PACKET_KEEPALIVE, slot, mInterval, mPacket); mNai.asyncChannel.sendMessage(CMD_START_SOCKET_KEEPALIVE, slot, mInterval, mPacket);
} else { } else {
handleStopKeepalive(mNai, mSlot, error); handleStopKeepalive(mNai, mSlot, error);
return; return;
@@ -214,7 +218,7 @@ public class KeepaliveTracker {
} }
if (isStarted) { if (isStarted) {
Log.d(TAG, "Stopping keepalive " + mSlot + " on " + mNai.name()); Log.d(TAG, "Stopping keepalive " + mSlot + " on " + mNai.name());
mNai.asyncChannel.sendMessage(CMD_STOP_PACKET_KEEPALIVE, mSlot); mNai.asyncChannel.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, mSlot);
} }
// TODO: at the moment we unconditionally return failure here. In cases where the // TODO: at the moment we unconditionally return failure here. In cases where the
// NetworkAgent is alive, should we ask it to reply, so it can return failure? // NetworkAgent is alive, should we ask it to reply, so it can return failure?
@@ -225,7 +229,7 @@ public class KeepaliveTracker {
void notifyMessenger(Messenger messenger, int slot, int err) { void notifyMessenger(Messenger messenger, int slot, int err) {
Message message = Message.obtain(); Message message = Message.obtain();
message.what = EVENT_PACKET_KEEPALIVE; message.what = EVENT_SOCKET_KEEPALIVE;
message.arg1 = slot; message.arg1 = slot;
message.arg2 = err; message.arg2 = err;
message.obj = null; message.obj = null;
@@ -310,7 +314,7 @@ public class KeepaliveTracker {
} }
/** Handle keepalive events from lower layer. */ /** Handle keepalive events from lower layer. */
public void handleEventPacketKeepalive(@NonNull NetworkAgentInfo nai, public void handleEventSocketKeepalive(@NonNull NetworkAgentInfo nai,
@NonNull Message message) { @NonNull Message message) {
int slot = message.arg1; int slot = message.arg1;
int reason = message.arg2; int reason = message.arg2;
@@ -369,16 +373,16 @@ public class KeepaliveTracker {
KeepalivePacketData packet; KeepalivePacketData packet;
try { try {
packet = KeepalivePacketData.nattKeepalivePacket( packet = NattKeepalivePacketData.nattKeepalivePacket(
srcAddress, srcPort, dstAddress, NATT_PORT); srcAddress, srcPort, dstAddress, NATT_PORT);
} catch (KeepalivePacketData.InvalidPacketException e) { } catch (InvalidPacketException e) {
notifyMessenger(messenger, NO_KEEPALIVE, e.error); notifyMessenger(messenger, NO_KEEPALIVE, e.error);
return; return;
} }
KeepaliveInfo ki = new KeepaliveInfo(messenger, binder, nai, packet, intervalSeconds); KeepaliveInfo ki = new KeepaliveInfo(messenger, binder, nai, packet, intervalSeconds);
Log.d(TAG, "Created keepalive: " + ki.toString()); Log.d(TAG, "Created keepalive: " + ki.toString());
mConnectivityServiceHandler.obtainMessage( mConnectivityServiceHandler.obtainMessage(
NetworkAgent.CMD_START_PACKET_KEEPALIVE, ki).sendToTarget(); CMD_START_SOCKET_KEEPALIVE, ki).sendToTarget();
} }
/** /**
@@ -432,7 +436,7 @@ public class KeepaliveTracker {
} }
public void dump(IndentingPrintWriter pw) { public void dump(IndentingPrintWriter pw) {
pw.println("Packet keepalives:"); pw.println("Socket keepalives:");
pw.increaseIndent(); pw.increaseIndent();
for (NetworkAgentInfo nai : mKeepalives.keySet()) { for (NetworkAgentInfo nai : mKeepalives.keySet()) {
pw.println(nai.name()); pw.println(nai.name());

View File

@@ -194,6 +194,7 @@ import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -500,17 +501,17 @@ public class ConnectivityServiceTest {
public void unwanted() { mDisconnected.open(); } public void unwanted() { mDisconnected.open(); }
@Override @Override
public void startPacketKeepalive(Message msg) { public void startSocketKeepalive(Message msg) {
int slot = msg.arg1; int slot = msg.arg1;
if (mExpectedKeepaliveSlot != null) { if (mExpectedKeepaliveSlot != null) {
assertEquals((int) mExpectedKeepaliveSlot, slot); assertEquals((int) mExpectedKeepaliveSlot, slot);
} }
onPacketKeepaliveEvent(slot, mStartKeepaliveError); onSocketKeepaliveEvent(slot, mStartKeepaliveError);
} }
@Override @Override
public void stopPacketKeepalive(Message msg) { public void stopSocketKeepalive(Message msg) {
onPacketKeepaliveEvent(msg.arg1, mStopKeepaliveError); onSocketKeepaliveEvent(msg.arg1, mStopKeepaliveError);
} }
@Override @Override
@@ -3791,10 +3792,17 @@ public class ConnectivityServiceTest {
@Test @Test
public void testNattSocketKeepalives() throws Exception { public void testNattSocketKeepalives() throws Exception {
final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
doTestNattSocketKeepalivesWithExecutor(executorSingleThread);
executorSingleThread.shutdown();
final Executor executorInline = (Runnable r) -> r.run();
doTestNattSocketKeepalivesWithExecutor(executorInline);
}
private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
// TODO: 1. Move this outside of ConnectivityServiceTest. // TODO: 1. Move this outside of ConnectivityServiceTest.
// 2. Add helper function to test against newSingleThreadExecutor as well as inline // 2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
// executor.
// 3. Make test to verify that Nat-T keepalive socket is created by IpSecService.
final int srcPort = 12345; final int srcPort = 12345;
final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129"); final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35"); final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
@@ -3808,8 +3816,6 @@ public class ConnectivityServiceTest {
final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE); final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket(srcPort); final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket(srcPort);
final Executor executor = Executors.newSingleThreadExecutor();
LinkProperties lp = new LinkProperties(); LinkProperties lp = new LinkProperties();
lp.setInterfaceName("wlan12"); lp.setInterfaceName("wlan12");
lp.addLinkAddress(new LinkAddress(myIPv6, 64)); lp.addLinkAddress(new LinkAddress(myIPv6, 64));
@@ -3926,6 +3932,11 @@ public class ConnectivityServiceTest {
ka2.stop(); ka2.stop();
callback2.expectStopped(); callback2.expectStopped();
testSocket.close();
testSocket2.close();
mWiFiNetworkAgent.disconnect();
} }
@Test @Test