Merge "[KA02] internal cleanup and refactor for SocketKeepalive" am: 292da961e6
am: 839c99be82
Change-Id: I242fdacdd70729367f60da80a1a27d8f5a08dff6
This commit is contained in:
@@ -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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
77
core/java/android/net/NattKeepalivePacketData.java
Normal file
77
core/java/android/net/NattKeepalivePacketData.java
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user