Merge "[KA02.5] Use binder thread and executor to invoke callback" am: f9ae70a41c am: c93f9c7f0e
am: 06ea4015bf
Change-Id: I881c1ab09187ab23facc03bb71cc38a7978e442c
This commit is contained in:
@@ -38,7 +38,6 @@ import android.os.Build;
|
|||||||
import android.os.Build.VERSION_CODES;
|
import android.os.Build.VERSION_CODES;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.HandlerThread;
|
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.INetworkActivityListener;
|
import android.os.INetworkActivityListener;
|
||||||
import android.os.INetworkManagementService;
|
import android.os.INetworkManagementService;
|
||||||
@@ -75,6 +74,9 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class that answers queries about the state of network connectivity. It also
|
* Class that answers queries about the state of network connectivity. It also
|
||||||
@@ -1813,23 +1815,26 @@ public class ConnectivityManager {
|
|||||||
public static final int MIN_INTERVAL = 10;
|
public static final int MIN_INTERVAL = 10;
|
||||||
|
|
||||||
private final Network mNetwork;
|
private final Network mNetwork;
|
||||||
private final PacketKeepaliveCallback mCallback;
|
private final ISocketKeepaliveCallback mCallback;
|
||||||
private final Looper mLooper;
|
private final ExecutorService mExecutor;
|
||||||
private final Messenger mMessenger;
|
|
||||||
|
|
||||||
private volatile Integer mSlot;
|
private volatile Integer mSlot;
|
||||||
|
|
||||||
void stopLooper() {
|
|
||||||
mLooper.quit();
|
|
||||||
}
|
|
||||||
|
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public void stop() {
|
public void stop() {
|
||||||
try {
|
try {
|
||||||
mService.stopKeepalive(mNetwork, mSlot);
|
mExecutor.execute(() -> {
|
||||||
} catch (RemoteException e) {
|
try {
|
||||||
Log.e(TAG, "Error stopping packet keepalive: ", e);
|
if (mSlot != null) {
|
||||||
stopLooper();
|
mService.stopKeepalive(mNetwork, mSlot);
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "Error stopping packet keepalive: ", e);
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (RejectedExecutionException e) {
|
||||||
|
// The internal executor has already stopped due to previous event.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1837,40 +1842,43 @@ public class ConnectivityManager {
|
|||||||
Preconditions.checkNotNull(network, "network cannot be null");
|
Preconditions.checkNotNull(network, "network cannot be null");
|
||||||
Preconditions.checkNotNull(callback, "callback cannot be null");
|
Preconditions.checkNotNull(callback, "callback cannot be null");
|
||||||
mNetwork = network;
|
mNetwork = network;
|
||||||
mCallback = callback;
|
mExecutor = Executors.newSingleThreadExecutor();
|
||||||
HandlerThread thread = new HandlerThread(TAG);
|
mCallback = new ISocketKeepaliveCallback.Stub() {
|
||||||
thread.start();
|
|
||||||
mLooper = thread.getLooper();
|
|
||||||
mMessenger = new Messenger(new Handler(mLooper) {
|
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message message) {
|
public void onStarted(int slot) {
|
||||||
switch (message.what) {
|
Binder.withCleanCallingIdentity(() ->
|
||||||
case NetworkAgent.EVENT_SOCKET_KEEPALIVE:
|
mExecutor.execute(() -> {
|
||||||
int error = message.arg2;
|
mSlot = slot;
|
||||||
try {
|
callback.onStarted();
|
||||||
if (error == SUCCESS) {
|
}));
|
||||||
if (mSlot == null) {
|
|
||||||
mSlot = message.arg1;
|
|
||||||
mCallback.onStarted();
|
|
||||||
} else {
|
|
||||||
mSlot = null;
|
|
||||||
stopLooper();
|
|
||||||
mCallback.onStopped();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
stopLooper();
|
|
||||||
mCallback.onError(error);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Exception in keepalive callback(" + error + ")", e);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Log.e(TAG, "Unhandled message " + Integer.toHexString(message.what));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
@Override
|
||||||
|
public void onStopped() {
|
||||||
|
Binder.withCleanCallingIdentity(() ->
|
||||||
|
mExecutor.execute(() -> {
|
||||||
|
mSlot = null;
|
||||||
|
callback.onStopped();
|
||||||
|
}));
|
||||||
|
mExecutor.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(int error) {
|
||||||
|
Binder.withCleanCallingIdentity(() ->
|
||||||
|
mExecutor.execute(() -> {
|
||||||
|
mSlot = null;
|
||||||
|
callback.onError(error);
|
||||||
|
}));
|
||||||
|
mExecutor.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataReceived() {
|
||||||
|
// PacketKeepalive is only used for Nat-T keepalive and as such does not invoke
|
||||||
|
// this callback when data is received.
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1887,12 +1895,11 @@ public class ConnectivityManager {
|
|||||||
InetAddress srcAddr, int srcPort, InetAddress dstAddr) {
|
InetAddress srcAddr, int srcPort, InetAddress dstAddr) {
|
||||||
final PacketKeepalive k = new PacketKeepalive(network, callback);
|
final PacketKeepalive k = new PacketKeepalive(network, callback);
|
||||||
try {
|
try {
|
||||||
mService.startNattKeepalive(network, intervalSeconds, k.mMessenger, new Binder(),
|
mService.startNattKeepalive(network, intervalSeconds, k.mCallback,
|
||||||
srcAddr.getHostAddress(), srcPort, dstAddr.getHostAddress());
|
srcAddr.getHostAddress(), srcPort, dstAddr.getHostAddress());
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(TAG, "Error starting packet keepalive: ", e);
|
Log.e(TAG, "Error starting packet keepalive: ", e);
|
||||||
k.stopLooper();
|
throw e.rethrowFromSystemServer();
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import android.net.NetworkMisc;
|
|||||||
import android.net.NetworkQuotaInfo;
|
import android.net.NetworkQuotaInfo;
|
||||||
import android.net.NetworkRequest;
|
import android.net.NetworkRequest;
|
||||||
import android.net.NetworkState;
|
import android.net.NetworkState;
|
||||||
|
import android.net.ISocketKeepaliveCallback;
|
||||||
import android.net.ProxyInfo;
|
import android.net.ProxyInfo;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
@@ -194,15 +195,15 @@ interface IConnectivityManager
|
|||||||
|
|
||||||
void factoryReset();
|
void factoryReset();
|
||||||
|
|
||||||
void startNattKeepalive(in Network network, int intervalSeconds, in Messenger messenger,
|
void startNattKeepalive(in Network network, int intervalSeconds,
|
||||||
in IBinder binder, String srcAddr, int srcPort, String dstAddr);
|
in ISocketKeepaliveCallback cb, String srcAddr, int srcPort, String dstAddr);
|
||||||
|
|
||||||
void startNattKeepaliveWithFd(in Network network, in FileDescriptor fd, int resourceId,
|
void startNattKeepaliveWithFd(in Network network, in FileDescriptor fd, int resourceId,
|
||||||
int intervalSeconds, in Messenger messenger, in IBinder binder, String srcAddr,
|
int intervalSeconds, in ISocketKeepaliveCallback cb, String srcAddr,
|
||||||
String dstAddr);
|
String dstAddr);
|
||||||
|
|
||||||
void startTcpKeepalive(in Network network, in FileDescriptor fd, int intervalSeconds,
|
void startTcpKeepalive(in Network network, in FileDescriptor fd, int intervalSeconds,
|
||||||
in Messenger messenger, in IBinder binder);
|
in ISocketKeepaliveCallback cb);
|
||||||
|
|
||||||
void stopKeepalive(in Network network, int slot);
|
void stopKeepalive(in Network network, int slot);
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
package android.net;
|
package android.net;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.os.Binder;
|
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@@ -52,24 +51,30 @@ public final class NattSocketKeepalive extends SocketKeepalive {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
void startImpl(int intervalSec) {
|
void startImpl(int intervalSec) {
|
||||||
try {
|
mExecutor.execute(() -> {
|
||||||
mService.startNattKeepaliveWithFd(mNetwork, mFd, mResourceId, intervalSec, mMessenger,
|
try {
|
||||||
new Binder(), mSource.getHostAddress(), mDestination.getHostAddress());
|
mService.startNattKeepaliveWithFd(mNetwork, mFd, mResourceId, intervalSec,
|
||||||
} catch (RemoteException e) {
|
mCallback,
|
||||||
Log.e(TAG, "Error starting packet keepalive: ", e);
|
mSource.getHostAddress(), mDestination.getHostAddress());
|
||||||
stopLooper();
|
} catch (RemoteException e) {
|
||||||
}
|
Log.e(TAG, "Error starting socket keepalive: ", e);
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void stopImpl() {
|
void stopImpl() {
|
||||||
try {
|
mExecutor.execute(() -> {
|
||||||
if (mSlot != null) {
|
try {
|
||||||
mService.stopKeepalive(mNetwork, mSlot);
|
if (mSlot != null) {
|
||||||
|
mService.stopKeepalive(mNetwork, mSlot);
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "Error stopping socket keepalive: ", e);
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
}
|
}
|
||||||
} catch (RemoteException e) {
|
});
|
||||||
Log.e(TAG, "Error stopping packet keepalive: ", e);
|
|
||||||
stopLooper();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,13 +20,8 @@ import android.annotation.IntDef;
|
|||||||
import android.annotation.IntRange;
|
import android.annotation.IntRange;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.os.Handler;
|
import android.os.Binder;
|
||||||
import android.os.HandlerThread;
|
import android.os.RemoteException;
|
||||||
import android.os.Looper;
|
|
||||||
import android.os.Message;
|
|
||||||
import android.os.Messenger;
|
|
||||||
import android.os.Process;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
@@ -152,10 +147,9 @@ public abstract class SocketKeepalive implements AutoCloseable {
|
|||||||
|
|
||||||
@NonNull final IConnectivityManager mService;
|
@NonNull final IConnectivityManager mService;
|
||||||
@NonNull final Network mNetwork;
|
@NonNull final Network mNetwork;
|
||||||
@NonNull private final Executor mExecutor;
|
@NonNull final Executor mExecutor;
|
||||||
@NonNull private final SocketKeepalive.Callback mCallback;
|
@NonNull final ISocketKeepaliveCallback mCallback;
|
||||||
@NonNull private final Looper mLooper;
|
// TODO: remove slot since mCallback could be used to identify which keepalive to stop.
|
||||||
@NonNull final Messenger mMessenger;
|
|
||||||
@Nullable Integer mSlot;
|
@Nullable Integer mSlot;
|
||||||
|
|
||||||
SocketKeepalive(@NonNull IConnectivityManager service, @NonNull Network network,
|
SocketKeepalive(@NonNull IConnectivityManager service, @NonNull Network network,
|
||||||
@@ -163,53 +157,53 @@ public abstract class SocketKeepalive implements AutoCloseable {
|
|||||||
mService = service;
|
mService = service;
|
||||||
mNetwork = network;
|
mNetwork = network;
|
||||||
mExecutor = executor;
|
mExecutor = executor;
|
||||||
mCallback = callback;
|
mCallback = new ISocketKeepaliveCallback.Stub() {
|
||||||
// TODO: 1. Use other thread modeling instead of create one thread for every instance to
|
|
||||||
// reduce the memory cost.
|
|
||||||
// 2. support restart.
|
|
||||||
// 3. Fix race condition which caused by rapidly start and stop.
|
|
||||||
HandlerThread thread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND
|
|
||||||
+ Process.THREAD_PRIORITY_LESS_FAVORABLE);
|
|
||||||
thread.start();
|
|
||||||
mLooper = thread.getLooper();
|
|
||||||
mMessenger = new Messenger(new Handler(mLooper) {
|
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message message) {
|
public void onStarted(int slot) {
|
||||||
switch (message.what) {
|
Binder.withCleanCallingIdentity(() ->
|
||||||
case NetworkAgent.EVENT_SOCKET_KEEPALIVE:
|
mExecutor.execute(() -> {
|
||||||
final int status = message.arg2;
|
mSlot = slot;
|
||||||
try {
|
callback.onStarted();
|
||||||
if (status == SUCCESS) {
|
}));
|
||||||
if (mSlot == null) {
|
|
||||||
mSlot = message.arg1;
|
|
||||||
mExecutor.execute(() -> mCallback.onStarted());
|
|
||||||
} else {
|
|
||||||
mSlot = null;
|
|
||||||
stopLooper();
|
|
||||||
mExecutor.execute(() -> mCallback.onStopped());
|
|
||||||
}
|
|
||||||
} else if (status == DATA_RECEIVED) {
|
|
||||||
stopLooper();
|
|
||||||
mExecutor.execute(() -> mCallback.onDataReceived());
|
|
||||||
} else {
|
|
||||||
stopLooper();
|
|
||||||
mExecutor.execute(() -> mCallback.onError(status));
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Exception in keepalive callback(" + status + ")", e);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Log.e(TAG, "Unhandled message " + Integer.toHexString(message.what));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
@Override
|
||||||
|
public void onStopped() {
|
||||||
|
Binder.withCleanCallingIdentity(() ->
|
||||||
|
executor.execute(() -> {
|
||||||
|
mSlot = null;
|
||||||
|
callback.onStopped();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(int error) {
|
||||||
|
Binder.withCleanCallingIdentity(() ->
|
||||||
|
executor.execute(() -> {
|
||||||
|
mSlot = null;
|
||||||
|
callback.onError(error);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataReceived() {
|
||||||
|
Binder.withCleanCallingIdentity(() ->
|
||||||
|
executor.execute(() -> {
|
||||||
|
mSlot = null;
|
||||||
|
callback.onDataReceived();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request that keepalive be started with the given {@code intervalSec}. See
|
* Request that keepalive be started with the given {@code intervalSec}. See
|
||||||
* {@link SocketKeepalive}.
|
* {@link SocketKeepalive}. If the remote binder dies, or the binder call throws an exception
|
||||||
|
* when invoking start or stop of the {@link SocketKeepalive}, a {@link RemoteException} will be
|
||||||
|
* thrown into the {@code executor}. This is typically not important to catch because the remote
|
||||||
|
* party is the system, so if it is not in shape to communicate through binder the system is
|
||||||
|
* probably going down anyway. If the caller cares regardless, it can use a custom
|
||||||
|
* {@link Executor} to catch the {@link RemoteException}.
|
||||||
*
|
*
|
||||||
* @param intervalSec The target interval in seconds between keepalive packet transmissions.
|
* @param intervalSec The target interval in seconds between keepalive packet transmissions.
|
||||||
* The interval should be between 10 seconds and 3600 seconds, otherwise
|
* The interval should be between 10 seconds and 3600 seconds, otherwise
|
||||||
@@ -222,12 +216,6 @@ public abstract class SocketKeepalive implements AutoCloseable {
|
|||||||
|
|
||||||
abstract void startImpl(int intervalSec);
|
abstract void startImpl(int intervalSec);
|
||||||
|
|
||||||
/** @hide */
|
|
||||||
protected void stopLooper() {
|
|
||||||
// TODO: remove this after changing thread modeling.
|
|
||||||
mLooper.quit();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests that keepalive be stopped. The application must wait for {@link Callback#onStopped}
|
* Requests that keepalive be stopped. The application must wait for {@link Callback#onStopped}
|
||||||
* before using the object. See {@link SocketKeepalive}.
|
* before using the object. See {@link SocketKeepalive}.
|
||||||
@@ -245,7 +233,6 @@ public abstract class SocketKeepalive implements AutoCloseable {
|
|||||||
@Override
|
@Override
|
||||||
public final void close() {
|
public final void close() {
|
||||||
stop();
|
stop();
|
||||||
stopLooper();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -259,7 +246,8 @@ public abstract class SocketKeepalive implements AutoCloseable {
|
|||||||
public void onStopped() {}
|
public void onStopped() {}
|
||||||
/** An error occurred. */
|
/** An error occurred. */
|
||||||
public void onError(@ErrorCode int error) {}
|
public void onError(@ErrorCode int error) {}
|
||||||
/** The keepalive on a TCP socket was stopped because the socket received data. */
|
/** The keepalive on a TCP socket was stopped because the socket received data. This is
|
||||||
|
* never called for UDP sockets. */
|
||||||
public void onDataReceived() {}
|
public void onDataReceived() {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
package android.net;
|
package android.net;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.os.Binder;
|
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@@ -56,24 +55,28 @@ final class TcpSocketKeepalive extends SocketKeepalive {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
void startImpl(int intervalSec) {
|
void startImpl(int intervalSec) {
|
||||||
try {
|
mExecutor.execute(() -> {
|
||||||
final FileDescriptor fd = mSocket.getFileDescriptor$();
|
try {
|
||||||
mService.startTcpKeepalive(mNetwork, fd, intervalSec, mMessenger, new Binder());
|
final FileDescriptor fd = mSocket.getFileDescriptor$();
|
||||||
} catch (RemoteException e) {
|
mService.startTcpKeepalive(mNetwork, fd, intervalSec, mCallback);
|
||||||
Log.e(TAG, "Error starting packet keepalive: ", e);
|
} catch (RemoteException e) {
|
||||||
stopLooper();
|
Log.e(TAG, "Error starting packet keepalive: ", e);
|
||||||
}
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void stopImpl() {
|
void stopImpl() {
|
||||||
try {
|
mExecutor.execute(() -> {
|
||||||
if (mSlot != null) {
|
try {
|
||||||
mService.stopKeepalive(mNetwork, mSlot);
|
if (mSlot != null) {
|
||||||
|
mService.stopKeepalive(mNetwork, mSlot);
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "Error stopping packet keepalive: ", e);
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
}
|
}
|
||||||
} catch (RemoteException e) {
|
});
|
||||||
Log.e(TAG, "Error stopping packet keepalive: ", e);
|
|
||||||
stopLooper();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ import android.net.INetworkMonitorCallbacks;
|
|||||||
import android.net.INetworkPolicyListener;
|
import android.net.INetworkPolicyListener;
|
||||||
import android.net.INetworkPolicyManager;
|
import android.net.INetworkPolicyManager;
|
||||||
import android.net.INetworkStatsService;
|
import android.net.INetworkStatsService;
|
||||||
|
import android.net.ISocketKeepaliveCallback;
|
||||||
import android.net.ITetheringEventCallback;
|
import android.net.ITetheringEventCallback;
|
||||||
import android.net.InetAddresses;
|
import android.net.InetAddresses;
|
||||||
import android.net.IpPrefix;
|
import android.net.IpPrefix;
|
||||||
@@ -6699,32 +6700,32 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startNattKeepalive(Network network, int intervalSeconds, Messenger messenger,
|
public void startNattKeepalive(Network network, int intervalSeconds,
|
||||||
IBinder binder, String srcAddr, int srcPort, String dstAddr) {
|
ISocketKeepaliveCallback cb, String srcAddr, int srcPort, String dstAddr) {
|
||||||
enforceKeepalivePermission();
|
enforceKeepalivePermission();
|
||||||
mKeepaliveTracker.startNattKeepalive(
|
mKeepaliveTracker.startNattKeepalive(
|
||||||
getNetworkAgentInfoForNetwork(network),
|
getNetworkAgentInfoForNetwork(network),
|
||||||
intervalSeconds, messenger, binder,
|
intervalSeconds, cb,
|
||||||
srcAddr, srcPort, dstAddr, NattSocketKeepalive.NATT_PORT);
|
srcAddr, srcPort, dstAddr, NattSocketKeepalive.NATT_PORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startNattKeepaliveWithFd(Network network, FileDescriptor fd, int resourceId,
|
public void startNattKeepaliveWithFd(Network network, FileDescriptor fd, int resourceId,
|
||||||
int intervalSeconds, Messenger messenger, IBinder binder, String srcAddr,
|
int intervalSeconds, ISocketKeepaliveCallback cb, String srcAddr,
|
||||||
String dstAddr) {
|
String dstAddr) {
|
||||||
enforceKeepalivePermission();
|
enforceKeepalivePermission();
|
||||||
mKeepaliveTracker.startNattKeepalive(
|
mKeepaliveTracker.startNattKeepalive(
|
||||||
getNetworkAgentInfoForNetwork(network), fd, resourceId,
|
getNetworkAgentInfoForNetwork(network), fd, resourceId,
|
||||||
intervalSeconds, messenger, binder,
|
intervalSeconds, cb,
|
||||||
srcAddr, dstAddr, NattSocketKeepalive.NATT_PORT);
|
srcAddr, dstAddr, NattSocketKeepalive.NATT_PORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startTcpKeepalive(Network network, FileDescriptor fd, int intervalSeconds,
|
public void startTcpKeepalive(Network network, FileDescriptor fd, int intervalSeconds,
|
||||||
Messenger messenger, IBinder binder) {
|
ISocketKeepaliveCallback cb) {
|
||||||
enforceKeepalivePermission();
|
enforceKeepalivePermission();
|
||||||
mKeepaliveTracker.startTcpKeepalive(
|
mKeepaliveTracker.startTcpKeepalive(
|
||||||
getNetworkAgentInfoForNetwork(network), fd, intervalSeconds, messenger, binder);
|
getNetworkAgentInfoForNetwork(network), fd, intervalSeconds, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ import static android.net.NetworkAgent.CMD_ADD_KEEPALIVE_PACKET_FILTER;
|
|||||||
import static android.net.NetworkAgent.CMD_REMOVE_KEEPALIVE_PACKET_FILTER;
|
import static android.net.NetworkAgent.CMD_REMOVE_KEEPALIVE_PACKET_FILTER;
|
||||||
import static android.net.NetworkAgent.CMD_START_SOCKET_KEEPALIVE;
|
import static android.net.NetworkAgent.CMD_START_SOCKET_KEEPALIVE;
|
||||||
import static android.net.NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE;
|
import static android.net.NetworkAgent.CMD_STOP_SOCKET_KEEPALIVE;
|
||||||
import static android.net.NetworkAgent.EVENT_SOCKET_KEEPALIVE;
|
|
||||||
import static android.net.SocketKeepalive.BINDER_DIED;
|
import static android.net.SocketKeepalive.BINDER_DIED;
|
||||||
|
import static android.net.SocketKeepalive.DATA_RECEIVED;
|
||||||
import static android.net.SocketKeepalive.ERROR_INVALID_INTERVAL;
|
import static android.net.SocketKeepalive.ERROR_INVALID_INTERVAL;
|
||||||
import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
|
import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
|
||||||
import static android.net.SocketKeepalive.ERROR_INVALID_NETWORK;
|
import static android.net.SocketKeepalive.ERROR_INVALID_NETWORK;
|
||||||
@@ -34,6 +34,7 @@ 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.ISocketKeepaliveCallback;
|
||||||
import android.net.KeepalivePacketData;
|
import android.net.KeepalivePacketData;
|
||||||
import android.net.NattKeepalivePacketData;
|
import android.net.NattKeepalivePacketData;
|
||||||
import android.net.NetworkAgent;
|
import android.net.NetworkAgent;
|
||||||
@@ -47,7 +48,6 @@ import android.os.Binder;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.Messenger;
|
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.system.ErrnoException;
|
import android.system.ErrnoException;
|
||||||
@@ -99,8 +99,7 @@ public class KeepaliveTracker {
|
|||||||
*/
|
*/
|
||||||
class KeepaliveInfo implements IBinder.DeathRecipient {
|
class KeepaliveInfo implements IBinder.DeathRecipient {
|
||||||
// Bookkeeping data.
|
// Bookkeeping data.
|
||||||
private final Messenger mMessenger;
|
private final ISocketKeepaliveCallback mCallback;
|
||||||
private final IBinder mBinder;
|
|
||||||
private final int mUid;
|
private final int mUid;
|
||||||
private final int mPid;
|
private final int mPid;
|
||||||
private final NetworkAgentInfo mNai;
|
private final NetworkAgentInfo mNai;
|
||||||
@@ -124,15 +123,13 @@ public class KeepaliveTracker {
|
|||||||
private static final int STARTED = 3;
|
private static final int STARTED = 3;
|
||||||
private int mStartedState = NOT_STARTED;
|
private int mStartedState = NOT_STARTED;
|
||||||
|
|
||||||
KeepaliveInfo(@NonNull Messenger messenger,
|
KeepaliveInfo(@NonNull ISocketKeepaliveCallback callback,
|
||||||
@NonNull IBinder binder,
|
|
||||||
@NonNull NetworkAgentInfo nai,
|
@NonNull NetworkAgentInfo nai,
|
||||||
@NonNull KeepalivePacketData packet,
|
@NonNull KeepalivePacketData packet,
|
||||||
int interval,
|
int interval,
|
||||||
int type,
|
int type,
|
||||||
@NonNull FileDescriptor fd) {
|
@NonNull FileDescriptor fd) {
|
||||||
mMessenger = messenger;
|
mCallback = callback;
|
||||||
mBinder = binder;
|
|
||||||
mPid = Binder.getCallingPid();
|
mPid = Binder.getCallingPid();
|
||||||
mUid = Binder.getCallingUid();
|
mUid = Binder.getCallingUid();
|
||||||
|
|
||||||
@@ -143,7 +140,7 @@ public class KeepaliveTracker {
|
|||||||
mFd = fd;
|
mFd = fd;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mBinder.linkToDeath(this, 0);
|
mCallback.asBinder().linkToDeath(this, 0);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
binderDied();
|
binderDied();
|
||||||
}
|
}
|
||||||
@@ -176,22 +173,14 @@ public class KeepaliveTracker {
|
|||||||
+ " ]";
|
+ " ]";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sends a message back to the application via its SocketKeepalive.Callback. */
|
|
||||||
void notifyMessenger(int slot, int err) {
|
|
||||||
if (DBG) {
|
|
||||||
Log.d(TAG, "notify keepalive " + mSlot + " on " + mNai.network + " for " + err);
|
|
||||||
}
|
|
||||||
KeepaliveTracker.this.notifyMessenger(mMessenger, slot, err);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Called when the application process is killed. */
|
/** Called when the application process is killed. */
|
||||||
public void binderDied() {
|
public void binderDied() {
|
||||||
stop(BINDER_DIED);
|
stop(BINDER_DIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unlinkDeathRecipient() {
|
void unlinkDeathRecipient() {
|
||||||
if (mBinder != null) {
|
if (mCallback != null) {
|
||||||
mBinder.unlinkToDeath(this, 0);
|
mCallback.asBinder().unlinkToDeath(this, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,9 +272,23 @@ public class KeepaliveTracker {
|
|||||||
Log.wtf(TAG, "Stopping keepalive with unknown type: " + mType);
|
Log.wtf(TAG, "Stopping keepalive with unknown type: " + mType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 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?
|
if (reason == SUCCESS) {
|
||||||
notifyMessenger(mSlot, reason);
|
try {
|
||||||
|
mCallback.onStopped();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.w(TAG, "Discarded onStop callback: " + reason);
|
||||||
|
}
|
||||||
|
} else if (reason == DATA_RECEIVED) {
|
||||||
|
try {
|
||||||
|
mCallback.onDataReceived();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.w(TAG, "Discarded onDataReceived callback: " + reason);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
notifyErrorCallback(mCallback, reason);
|
||||||
|
}
|
||||||
|
|
||||||
unlinkDeathRecipient();
|
unlinkDeathRecipient();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,16 +297,12 @@ public class KeepaliveTracker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void notifyMessenger(Messenger messenger, int slot, int err) {
|
void notifyErrorCallback(ISocketKeepaliveCallback cb, int error) {
|
||||||
Message message = Message.obtain();
|
if (DBG) Log.w(TAG, "Sending onError(" + error + ") callback");
|
||||||
message.what = EVENT_SOCKET_KEEPALIVE;
|
|
||||||
message.arg1 = slot;
|
|
||||||
message.arg2 = err;
|
|
||||||
message.obj = null;
|
|
||||||
try {
|
try {
|
||||||
messenger.send(message);
|
cb.onError(error);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// Process died?
|
Log.w(TAG, "Discarded onError(" + error + ") callback");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,7 +413,11 @@ public class KeepaliveTracker {
|
|||||||
// Keepalive successfully started.
|
// Keepalive successfully started.
|
||||||
if (DBG) Log.d(TAG, "Started keepalive " + slot + " on " + nai.name());
|
if (DBG) Log.d(TAG, "Started keepalive " + slot + " on " + nai.name());
|
||||||
ki.mStartedState = KeepaliveInfo.STARTED;
|
ki.mStartedState = KeepaliveInfo.STARTED;
|
||||||
ki.notifyMessenger(slot, reason);
|
try {
|
||||||
|
ki.mCallback.onStarted(slot);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.w(TAG, "Discarded onStarted(" + slot + ") callback");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Keepalive successfully stopped, or error.
|
// Keepalive successfully stopped, or error.
|
||||||
ki.mStartedState = KeepaliveInfo.NOT_STARTED;
|
ki.mStartedState = KeepaliveInfo.NOT_STARTED;
|
||||||
@@ -436,14 +439,13 @@ public class KeepaliveTracker {
|
|||||||
**/
|
**/
|
||||||
public void startNattKeepalive(@Nullable NetworkAgentInfo nai,
|
public void startNattKeepalive(@Nullable NetworkAgentInfo nai,
|
||||||
int intervalSeconds,
|
int intervalSeconds,
|
||||||
@NonNull Messenger messenger,
|
@NonNull ISocketKeepaliveCallback cb,
|
||||||
@NonNull IBinder binder,
|
|
||||||
@NonNull String srcAddrString,
|
@NonNull String srcAddrString,
|
||||||
int srcPort,
|
int srcPort,
|
||||||
@NonNull String dstAddrString,
|
@NonNull String dstAddrString,
|
||||||
int dstPort) {
|
int dstPort) {
|
||||||
if (nai == null) {
|
if (nai == null) {
|
||||||
notifyMessenger(messenger, NO_KEEPALIVE, ERROR_INVALID_NETWORK);
|
notifyErrorCallback(cb, ERROR_INVALID_NETWORK);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,7 +454,7 @@ public class KeepaliveTracker {
|
|||||||
srcAddress = NetworkUtils.numericToInetAddress(srcAddrString);
|
srcAddress = NetworkUtils.numericToInetAddress(srcAddrString);
|
||||||
dstAddress = NetworkUtils.numericToInetAddress(dstAddrString);
|
dstAddress = NetworkUtils.numericToInetAddress(dstAddrString);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
notifyMessenger(messenger, NO_KEEPALIVE, ERROR_INVALID_IP_ADDRESS);
|
notifyErrorCallback(cb, ERROR_INVALID_IP_ADDRESS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -461,11 +463,12 @@ public class KeepaliveTracker {
|
|||||||
packet = NattKeepalivePacketData.nattKeepalivePacket(
|
packet = NattKeepalivePacketData.nattKeepalivePacket(
|
||||||
srcAddress, srcPort, dstAddress, NATT_PORT);
|
srcAddress, srcPort, dstAddress, NATT_PORT);
|
||||||
} catch (InvalidPacketException e) {
|
} catch (InvalidPacketException e) {
|
||||||
notifyMessenger(messenger, NO_KEEPALIVE, e.error);
|
notifyErrorCallback(cb, e.error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
KeepaliveInfo ki = new KeepaliveInfo(messenger, binder, nai, packet, intervalSeconds,
|
KeepaliveInfo ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds,
|
||||||
KeepaliveInfo.TYPE_NATT, null);
|
KeepaliveInfo.TYPE_NATT, null);
|
||||||
|
Log.d(TAG, "Created keepalive: " + ki.toString());
|
||||||
mConnectivityServiceHandler.obtainMessage(
|
mConnectivityServiceHandler.obtainMessage(
|
||||||
NetworkAgent.CMD_START_SOCKET_KEEPALIVE, ki).sendToTarget();
|
NetworkAgent.CMD_START_SOCKET_KEEPALIVE, ki).sendToTarget();
|
||||||
}
|
}
|
||||||
@@ -483,10 +486,9 @@ public class KeepaliveTracker {
|
|||||||
public void startTcpKeepalive(@Nullable NetworkAgentInfo nai,
|
public void startTcpKeepalive(@Nullable NetworkAgentInfo nai,
|
||||||
@NonNull FileDescriptor fd,
|
@NonNull FileDescriptor fd,
|
||||||
int intervalSeconds,
|
int intervalSeconds,
|
||||||
@NonNull Messenger messenger,
|
@NonNull ISocketKeepaliveCallback cb) {
|
||||||
@NonNull IBinder binder) {
|
|
||||||
if (nai == null) {
|
if (nai == null) {
|
||||||
notifyMessenger(messenger, NO_KEEPALIVE, ERROR_INVALID_NETWORK);
|
notifyErrorCallback(cb, ERROR_INVALID_NETWORK);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -500,10 +502,10 @@ public class KeepaliveTracker {
|
|||||||
} catch (ErrnoException e1) {
|
} catch (ErrnoException e1) {
|
||||||
Log.e(TAG, "Couldn't move fd out of repair mode after failure to start keepalive");
|
Log.e(TAG, "Couldn't move fd out of repair mode after failure to start keepalive");
|
||||||
}
|
}
|
||||||
notifyMessenger(messenger, NO_KEEPALIVE, e.error);
|
notifyErrorCallback(cb, e.error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
KeepaliveInfo ki = new KeepaliveInfo(messenger, binder, nai, packet, intervalSeconds,
|
KeepaliveInfo ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds,
|
||||||
KeepaliveInfo.TYPE_TCP, fd);
|
KeepaliveInfo.TYPE_TCP, fd);
|
||||||
Log.d(TAG, "Created keepalive: " + ki.toString());
|
Log.d(TAG, "Created keepalive: " + ki.toString());
|
||||||
mConnectivityServiceHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, ki).sendToTarget();
|
mConnectivityServiceHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, ki).sendToTarget();
|
||||||
@@ -520,14 +522,13 @@ public class KeepaliveTracker {
|
|||||||
@Nullable FileDescriptor fd,
|
@Nullable FileDescriptor fd,
|
||||||
int resourceId,
|
int resourceId,
|
||||||
int intervalSeconds,
|
int intervalSeconds,
|
||||||
@NonNull Messenger messenger,
|
@NonNull ISocketKeepaliveCallback cb,
|
||||||
@NonNull IBinder binder,
|
|
||||||
@NonNull String srcAddrString,
|
@NonNull String srcAddrString,
|
||||||
@NonNull String dstAddrString,
|
@NonNull String dstAddrString,
|
||||||
int dstPort) {
|
int dstPort) {
|
||||||
// Ensure that the socket is created by IpSecService.
|
// Ensure that the socket is created by IpSecService.
|
||||||
if (!isNattKeepaliveSocketValid(fd, resourceId)) {
|
if (!isNattKeepaliveSocketValid(fd, resourceId)) {
|
||||||
notifyMessenger(messenger, NO_KEEPALIVE, ERROR_INVALID_SOCKET);
|
notifyErrorCallback(cb, ERROR_INVALID_SOCKET);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get src port to adopt old API.
|
// Get src port to adopt old API.
|
||||||
@@ -536,11 +537,11 @@ public class KeepaliveTracker {
|
|||||||
final SocketAddress srcSockAddr = Os.getsockname(fd);
|
final SocketAddress srcSockAddr = Os.getsockname(fd);
|
||||||
srcPort = ((InetSocketAddress) srcSockAddr).getPort();
|
srcPort = ((InetSocketAddress) srcSockAddr).getPort();
|
||||||
} catch (ErrnoException e) {
|
} catch (ErrnoException e) {
|
||||||
notifyMessenger(messenger, NO_KEEPALIVE, ERROR_INVALID_SOCKET);
|
notifyErrorCallback(cb, ERROR_INVALID_SOCKET);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forward request to old API.
|
// Forward request to old API.
|
||||||
startNattKeepalive(nai, intervalSeconds, messenger, binder, srcAddrString, srcPort,
|
startNattKeepalive(nai, intervalSeconds, cb, srcAddrString, srcPort,
|
||||||
dstAddrString, dstPort);
|
dstAddrString, dstPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ import static android.net.shared.NetworkParcelableUtil.fromStableParcelable;
|
|||||||
|
|
||||||
import static com.android.internal.util.TestUtils.waitForIdleHandler;
|
import static com.android.internal.util.TestUtils.waitForIdleHandler;
|
||||||
import static com.android.internal.util.TestUtils.waitForIdleLooper;
|
import static com.android.internal.util.TestUtils.waitForIdleLooper;
|
||||||
|
import static com.android.internal.util.TestUtils.waitForIdleSerialExecutor;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
@@ -88,6 +89,7 @@ import static org.mockito.Mockito.verify;
|
|||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
@@ -3762,7 +3764,7 @@ public class ConnectivityServiceTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
|
private final LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStarted() {
|
public void onStarted() {
|
||||||
@@ -3837,6 +3839,11 @@ public class ConnectivityServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
|
private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
|
||||||
|
private final Executor mExecutor;
|
||||||
|
|
||||||
|
TestSocketKeepaliveCallback(@NonNull Executor executor) {
|
||||||
|
mExecutor = executor;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStarted() {
|
public void onStarted() {
|
||||||
@@ -3874,6 +3881,12 @@ public class ConnectivityServiceTest {
|
|||||||
public void expectError(int error) {
|
public void expectError(int error) {
|
||||||
expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
|
expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void assertNoCallback() {
|
||||||
|
waitForIdleSerialExecutor(mExecutor, TIMEOUT_MS);
|
||||||
|
CallbackValue cv = mCallbacks.peek();
|
||||||
|
assertNull("Unexpected callback: " + cv, cv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Network connectKeepaliveNetwork(LinkProperties lp) {
|
private Network connectKeepaliveNetwork(LinkProperties lp) {
|
||||||
@@ -3980,19 +3993,6 @@ public class ConnectivityServiceTest {
|
|||||||
myNet = connectKeepaliveNetwork(lp);
|
myNet = connectKeepaliveNetwork(lp);
|
||||||
mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
|
mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
|
||||||
|
|
||||||
// Check things work as expected when the keepalive is stopped and the network disconnects.
|
|
||||||
ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
|
|
||||||
callback.expectStarted();
|
|
||||||
ka.stop();
|
|
||||||
mWiFiNetworkAgent.disconnect();
|
|
||||||
waitFor(mWiFiNetworkAgent.getDisconnectedCV());
|
|
||||||
waitForIdle();
|
|
||||||
callback.expectStopped();
|
|
||||||
|
|
||||||
// Reconnect.
|
|
||||||
myNet = connectKeepaliveNetwork(lp);
|
|
||||||
mWiFiNetworkAgent.setStartKeepaliveError(PacketKeepalive.SUCCESS);
|
|
||||||
|
|
||||||
// Check that keepalive slots start from 1 and increment. The first one gets slot 1.
|
// Check that keepalive slots start from 1 and increment. The first one gets slot 1.
|
||||||
mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
|
mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
|
||||||
ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
|
ka = mCm.startNattKeepalive(myNet, validKaInterval, callback, myIPv4, 12345, dstIPv4);
|
||||||
@@ -4068,7 +4068,7 @@ public class ConnectivityServiceTest {
|
|||||||
Network notMyNet = new Network(61234);
|
Network notMyNet = new Network(61234);
|
||||||
Network myNet = connectKeepaliveNetwork(lp);
|
Network myNet = connectKeepaliveNetwork(lp);
|
||||||
|
|
||||||
TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback();
|
TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
|
||||||
SocketKeepalive ka;
|
SocketKeepalive ka;
|
||||||
|
|
||||||
// Attempt to start keepalives with invalid parameters and check for errors.
|
// Attempt to start keepalives with invalid parameters and check for errors.
|
||||||
@@ -4111,6 +4111,22 @@ public class ConnectivityServiceTest {
|
|||||||
ka.stop();
|
ka.stop();
|
||||||
callback.expectStopped();
|
callback.expectStopped();
|
||||||
|
|
||||||
|
// Check that keepalive could be restarted.
|
||||||
|
ka.start(validKaInterval);
|
||||||
|
callback.expectStarted();
|
||||||
|
ka.stop();
|
||||||
|
callback.expectStopped();
|
||||||
|
|
||||||
|
// Check that keepalive can be restarted without waiting for callback.
|
||||||
|
ka.start(validKaInterval);
|
||||||
|
callback.expectStarted();
|
||||||
|
ka.stop();
|
||||||
|
ka.start(validKaInterval);
|
||||||
|
callback.expectStopped();
|
||||||
|
callback.expectStarted();
|
||||||
|
ka.stop();
|
||||||
|
callback.expectStopped();
|
||||||
|
|
||||||
// Check that deleting the IP address stops the keepalive.
|
// Check that deleting the IP address stops the keepalive.
|
||||||
LinkProperties bogusLp = new LinkProperties(lp);
|
LinkProperties bogusLp = new LinkProperties(lp);
|
||||||
ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
|
ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
|
||||||
@@ -4135,20 +4151,7 @@ public class ConnectivityServiceTest {
|
|||||||
final Network myNetAlias = myNet;
|
final Network myNetAlias = myNet;
|
||||||
assertNull(mCm.getNetworkCapabilities(myNetAlias));
|
assertNull(mCm.getNetworkCapabilities(myNetAlias));
|
||||||
ka.stop();
|
ka.stop();
|
||||||
|
callback.assertNoCallback();
|
||||||
// Reconnect.
|
|
||||||
myNet = connectKeepaliveNetwork(lp);
|
|
||||||
mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
|
|
||||||
|
|
||||||
// Check things work as expected when the keepalive is stopped and the network disconnects.
|
|
||||||
ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
|
|
||||||
ka.start(validKaInterval);
|
|
||||||
callback.expectStarted();
|
|
||||||
ka.stop();
|
|
||||||
mWiFiNetworkAgent.disconnect();
|
|
||||||
waitFor(mWiFiNetworkAgent.getDisconnectedCV());
|
|
||||||
waitForIdle();
|
|
||||||
callback.expectStopped();
|
|
||||||
|
|
||||||
// Reconnect.
|
// Reconnect.
|
||||||
myNet = connectKeepaliveNetwork(lp);
|
myNet = connectKeepaliveNetwork(lp);
|
||||||
@@ -4163,7 +4166,7 @@ public class ConnectivityServiceTest {
|
|||||||
// The second one gets slot 2.
|
// The second one gets slot 2.
|
||||||
mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
|
mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
|
||||||
final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket(6789);
|
final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket(6789);
|
||||||
TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback();
|
TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
|
||||||
SocketKeepalive ka2 =
|
SocketKeepalive ka2 =
|
||||||
mCm.createSocketKeepalive(myNet, testSocket2, myIPv4, dstIPv4, executor, callback2);
|
mCm.createSocketKeepalive(myNet, testSocket2, myIPv4, dstIPv4, executor, callback2);
|
||||||
ka2.start(validKaInterval);
|
ka2.start(validKaInterval);
|
||||||
@@ -4216,7 +4219,7 @@ public class ConnectivityServiceTest {
|
|||||||
final Socket testSocketV4 = new Socket();
|
final Socket testSocketV4 = new Socket();
|
||||||
final Socket testSocketV6 = new Socket();
|
final Socket testSocketV6 = new Socket();
|
||||||
|
|
||||||
TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback();
|
TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(executor);
|
||||||
SocketKeepalive ka;
|
SocketKeepalive ka;
|
||||||
|
|
||||||
// Attempt to start Tcp keepalives with invalid parameters and check for errors.
|
// Attempt to start Tcp keepalives with invalid parameters and check for errors.
|
||||||
|
|||||||
Reference in New Issue
Block a user