Merge changes Ib439bde4,I5bc0fe94,I72abf1e2,Id1813bcb
* changes: Call setUnderlyingNetwork to complete VCN MOBIKE Rename isRunning to isQuitting, and flip all booleans Notify Vcn of VcnGatewayConnection quits Allow NETWORK_LOST disconnections to retry
This commit is contained in:
@@ -65,7 +65,7 @@ public class UnderlyingNetworkTracker {
|
|||||||
@NonNull private final NetworkCallback mRouteSelectionCallback = new RouteSelectionCallback();
|
@NonNull private final NetworkCallback mRouteSelectionCallback = new RouteSelectionCallback();
|
||||||
|
|
||||||
@NonNull private TelephonySubscriptionSnapshot mLastSnapshot;
|
@NonNull private TelephonySubscriptionSnapshot mLastSnapshot;
|
||||||
private boolean mIsRunning = true;
|
private boolean mIsQuitting = false;
|
||||||
|
|
||||||
@Nullable private UnderlyingNetworkRecord mCurrentRecord;
|
@Nullable private UnderlyingNetworkRecord mCurrentRecord;
|
||||||
@Nullable private UnderlyingNetworkRecord.Builder mRecordInProgress;
|
@Nullable private UnderlyingNetworkRecord.Builder mRecordInProgress;
|
||||||
@@ -151,7 +151,7 @@ public class UnderlyingNetworkTracker {
|
|||||||
mVcnContext.ensureRunningOnLooperThread();
|
mVcnContext.ensureRunningOnLooperThread();
|
||||||
|
|
||||||
// Don't bother re-filing NetworkRequests if this Tracker has been torn down.
|
// Don't bother re-filing NetworkRequests if this Tracker has been torn down.
|
||||||
if (!mIsRunning) {
|
if (mIsQuitting) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,7 +205,7 @@ public class UnderlyingNetworkTracker {
|
|||||||
}
|
}
|
||||||
mCellBringupCallbacks.clear();
|
mCellBringupCallbacks.clear();
|
||||||
|
|
||||||
mIsRunning = false;
|
mIsQuitting = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns whether the currently selected Network matches the given network. */
|
/** Returns whether the currently selected Network matches the given network. */
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.android.server.vcn;
|
package com.android.server.vcn;
|
||||||
|
|
||||||
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
|
||||||
|
|
||||||
import static com.android.server.VcnManagementService.VDBG;
|
import static com.android.server.VcnManagementService.VDBG;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
@@ -84,6 +86,13 @@ public class Vcn extends Handler {
|
|||||||
*/
|
*/
|
||||||
private static final int MSG_EVENT_SUBSCRIPTIONS_CHANGED = MSG_EVENT_BASE + 2;
|
private static final int MSG_EVENT_SUBSCRIPTIONS_CHANGED = MSG_EVENT_BASE + 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A GatewayConnection owned by this VCN quit.
|
||||||
|
*
|
||||||
|
* @param obj VcnGatewayConnectionConfig
|
||||||
|
*/
|
||||||
|
private static final int MSG_EVENT_GATEWAY_CONNECTION_QUIT = MSG_EVENT_BASE + 3;
|
||||||
|
|
||||||
/** Triggers an immediate teardown of the entire Vcn, including GatewayConnections. */
|
/** Triggers an immediate teardown of the entire Vcn, including GatewayConnections. */
|
||||||
private static final int MSG_CMD_TEARDOWN = MSG_CMD_BASE;
|
private static final int MSG_CMD_TEARDOWN = MSG_CMD_BASE;
|
||||||
|
|
||||||
@@ -208,6 +217,9 @@ public class Vcn extends Handler {
|
|||||||
case MSG_EVENT_SUBSCRIPTIONS_CHANGED:
|
case MSG_EVENT_SUBSCRIPTIONS_CHANGED:
|
||||||
handleSubscriptionsChanged((TelephonySubscriptionSnapshot) msg.obj);
|
handleSubscriptionsChanged((TelephonySubscriptionSnapshot) msg.obj);
|
||||||
break;
|
break;
|
||||||
|
case MSG_EVENT_GATEWAY_CONNECTION_QUIT:
|
||||||
|
handleGatewayConnectionQuit((VcnGatewayConnectionConfig) msg.obj);
|
||||||
|
break;
|
||||||
case MSG_CMD_TEARDOWN:
|
case MSG_CMD_TEARDOWN:
|
||||||
handleTeardown();
|
handleTeardown();
|
||||||
break;
|
break;
|
||||||
@@ -263,7 +275,7 @@ public class Vcn extends Handler {
|
|||||||
|
|
||||||
// If preexisting VcnGatewayConnection(s) satisfy request, return
|
// If preexisting VcnGatewayConnection(s) satisfy request, return
|
||||||
for (VcnGatewayConnectionConfig gatewayConnectionConfig : mVcnGatewayConnections.keySet()) {
|
for (VcnGatewayConnectionConfig gatewayConnectionConfig : mVcnGatewayConnections.keySet()) {
|
||||||
if (requestSatisfiedByGatewayConnectionConfig(request, gatewayConnectionConfig)) {
|
if (isRequestSatisfiedByGatewayConnectionConfig(request, gatewayConnectionConfig)) {
|
||||||
if (VDBG) {
|
if (VDBG) {
|
||||||
Slog.v(
|
Slog.v(
|
||||||
getLogTag(),
|
getLogTag(),
|
||||||
@@ -278,7 +290,7 @@ public class Vcn extends Handler {
|
|||||||
// up
|
// up
|
||||||
for (VcnGatewayConnectionConfig gatewayConnectionConfig :
|
for (VcnGatewayConnectionConfig gatewayConnectionConfig :
|
||||||
mConfig.getGatewayConnectionConfigs()) {
|
mConfig.getGatewayConnectionConfigs()) {
|
||||||
if (requestSatisfiedByGatewayConnectionConfig(request, gatewayConnectionConfig)) {
|
if (isRequestSatisfiedByGatewayConnectionConfig(request, gatewayConnectionConfig)) {
|
||||||
Slog.v(
|
Slog.v(
|
||||||
getLogTag(),
|
getLogTag(),
|
||||||
"Bringing up new VcnGatewayConnection for request " + request.requestId);
|
"Bringing up new VcnGatewayConnection for request " + request.requestId);
|
||||||
@@ -289,12 +301,21 @@ public class Vcn extends Handler {
|
|||||||
mSubscriptionGroup,
|
mSubscriptionGroup,
|
||||||
mLastSnapshot,
|
mLastSnapshot,
|
||||||
gatewayConnectionConfig,
|
gatewayConnectionConfig,
|
||||||
new VcnGatewayStatusCallbackImpl());
|
new VcnGatewayStatusCallbackImpl(gatewayConnectionConfig));
|
||||||
mVcnGatewayConnections.put(gatewayConnectionConfig, vcnGatewayConnection);
|
mVcnGatewayConnections.put(gatewayConnectionConfig, vcnGatewayConnection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleGatewayConnectionQuit(VcnGatewayConnectionConfig config) {
|
||||||
|
Slog.v(getLogTag(), "VcnGatewayConnection quit: " + config);
|
||||||
|
mVcnGatewayConnections.remove(config);
|
||||||
|
|
||||||
|
// Trigger a re-evaluation of all NetworkRequests (to make sure any that can be satisfied
|
||||||
|
// start a new GatewayConnection)
|
||||||
|
mVcnContext.getVcnNetworkProvider().resendAllRequests(mRequestListener);
|
||||||
|
}
|
||||||
|
|
||||||
private void handleSubscriptionsChanged(@NonNull TelephonySubscriptionSnapshot snapshot) {
|
private void handleSubscriptionsChanged(@NonNull TelephonySubscriptionSnapshot snapshot) {
|
||||||
mLastSnapshot = snapshot;
|
mLastSnapshot = snapshot;
|
||||||
|
|
||||||
@@ -305,9 +326,10 @@ public class Vcn extends Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean requestSatisfiedByGatewayConnectionConfig(
|
private boolean isRequestSatisfiedByGatewayConnectionConfig(
|
||||||
@NonNull NetworkRequest request, @NonNull VcnGatewayConnectionConfig config) {
|
@NonNull NetworkRequest request, @NonNull VcnGatewayConnectionConfig config) {
|
||||||
final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder();
|
final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder();
|
||||||
|
builder.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
|
||||||
for (int cap : config.getAllExposedCapabilities()) {
|
for (int cap : config.getAllExposedCapabilities()) {
|
||||||
builder.addCapability(cap);
|
builder.addCapability(cap);
|
||||||
}
|
}
|
||||||
@@ -339,9 +361,23 @@ public class Vcn extends Handler {
|
|||||||
@VcnErrorCode int errorCode,
|
@VcnErrorCode int errorCode,
|
||||||
@Nullable String exceptionClass,
|
@Nullable String exceptionClass,
|
||||||
@Nullable String exceptionMessage);
|
@Nullable String exceptionMessage);
|
||||||
|
|
||||||
|
/** Called by a VcnGatewayConnection to indicate that it has fully torn down. */
|
||||||
|
void onQuit();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class VcnGatewayStatusCallbackImpl implements VcnGatewayStatusCallback {
|
private class VcnGatewayStatusCallbackImpl implements VcnGatewayStatusCallback {
|
||||||
|
public final VcnGatewayConnectionConfig mGatewayConnectionConfig;
|
||||||
|
|
||||||
|
VcnGatewayStatusCallbackImpl(VcnGatewayConnectionConfig gatewayConnectionConfig) {
|
||||||
|
mGatewayConnectionConfig = gatewayConnectionConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onQuit() {
|
||||||
|
sendMessage(obtainMessage(MSG_EVENT_GATEWAY_CONNECTION_QUIT, mGatewayConnectionConfig));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnteredSafeMode() {
|
public void onEnteredSafeMode() {
|
||||||
sendMessage(obtainMessage(MSG_CMD_ENTER_SAFE_MODE));
|
sendMessage(obtainMessage(MSG_CMD_ENTER_SAFE_MODE));
|
||||||
|
|||||||
@@ -168,6 +168,8 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
private static final String DISCONNECT_REASON_INTERNAL_ERROR = "Uncaught exception: ";
|
private static final String DISCONNECT_REASON_INTERNAL_ERROR = "Uncaught exception: ";
|
||||||
private static final String DISCONNECT_REASON_UNDERLYING_NETWORK_LOST =
|
private static final String DISCONNECT_REASON_UNDERLYING_NETWORK_LOST =
|
||||||
"Underlying Network lost";
|
"Underlying Network lost";
|
||||||
|
private static final String DISCONNECT_REASON_NETWORK_AGENT_UNWANTED =
|
||||||
|
"NetworkAgent was unwanted";
|
||||||
private static final String DISCONNECT_REASON_TEARDOWN = "teardown() called on VcnTunnel";
|
private static final String DISCONNECT_REASON_TEARDOWN = "teardown() called on VcnTunnel";
|
||||||
private static final int TOKEN_ALL = Integer.MIN_VALUE;
|
private static final int TOKEN_ALL = Integer.MIN_VALUE;
|
||||||
|
|
||||||
@@ -379,13 +381,16 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
/** The reason why the disconnect was requested. */
|
/** The reason why the disconnect was requested. */
|
||||||
@NonNull public final String reason;
|
@NonNull public final String reason;
|
||||||
|
|
||||||
EventDisconnectRequestedInfo(@NonNull String reason) {
|
public final boolean shouldQuit;
|
||||||
|
|
||||||
|
EventDisconnectRequestedInfo(@NonNull String reason, boolean shouldQuit) {
|
||||||
this.reason = Objects.requireNonNull(reason);
|
this.reason = Objects.requireNonNull(reason);
|
||||||
|
this.shouldQuit = shouldQuit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(reason);
|
return Objects.hash(reason, shouldQuit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -395,7 +400,7 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final EventDisconnectRequestedInfo rhs = (EventDisconnectRequestedInfo) other;
|
final EventDisconnectRequestedInfo rhs = (EventDisconnectRequestedInfo) other;
|
||||||
return reason.equals(rhs.reason);
|
return reason.equals(rhs.reason) && shouldQuit == rhs.shouldQuit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,8 +493,14 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
*/
|
*/
|
||||||
@NonNull private final VcnWakeLock mWakeLock;
|
@NonNull private final VcnWakeLock mWakeLock;
|
||||||
|
|
||||||
/** Running state of this VcnGatewayConnection. */
|
/**
|
||||||
private boolean mIsRunning = true;
|
* Whether the VcnGatewayConnection is in the process of irreversibly quitting.
|
||||||
|
*
|
||||||
|
* <p>This variable is false for the lifecycle of the VcnGatewayConnection, until a command to
|
||||||
|
* teardown has been received. This may be flipped due to events such as the Network becoming
|
||||||
|
* unwanted, the owning VCN entering safe mode, or an irrecoverable internal failure.
|
||||||
|
*/
|
||||||
|
private boolean mIsQuitting = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The token used by the primary/current/active session.
|
* The token used by the primary/current/active session.
|
||||||
@@ -622,10 +633,8 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
* <p>Once torn down, this VcnTunnel CANNOT be started again.
|
* <p>Once torn down, this VcnTunnel CANNOT be started again.
|
||||||
*/
|
*/
|
||||||
public void teardownAsynchronously() {
|
public void teardownAsynchronously() {
|
||||||
sendMessageAndAcquireWakeLock(
|
sendDisconnectRequestedAndAcquireWakelock(
|
||||||
EVENT_DISCONNECT_REQUESTED,
|
DISCONNECT_REASON_TEARDOWN, true /* shouldQuit */);
|
||||||
TOKEN_ALL,
|
|
||||||
new EventDisconnectRequestedInfo(DISCONNECT_REASON_TEARDOWN));
|
|
||||||
|
|
||||||
// TODO: Notify VcnInstance (via callbacks) of permanent teardown of this tunnel, since this
|
// TODO: Notify VcnInstance (via callbacks) of permanent teardown of this tunnel, since this
|
||||||
// is also called asynchronously when a NetworkAgent becomes unwanted
|
// is also called asynchronously when a NetworkAgent becomes unwanted
|
||||||
@@ -646,6 +655,8 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
cancelSafeModeAlarm();
|
cancelSafeModeAlarm();
|
||||||
|
|
||||||
mUnderlyingNetworkTracker.teardown();
|
mUnderlyingNetworkTracker.teardown();
|
||||||
|
|
||||||
|
mGatewayStatusCallback.onQuit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -693,7 +704,7 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
private void acquireWakeLock() {
|
private void acquireWakeLock() {
|
||||||
mVcnContext.ensureRunningOnLooperThread();
|
mVcnContext.ensureRunningOnLooperThread();
|
||||||
|
|
||||||
if (mIsRunning) {
|
if (!mIsQuitting) {
|
||||||
mWakeLock.acquire();
|
mWakeLock.acquire();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -892,7 +903,7 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
TOKEN_ALL,
|
TOKEN_ALL,
|
||||||
0 /* arg2 */,
|
0 /* arg2 */,
|
||||||
new EventDisconnectRequestedInfo(
|
new EventDisconnectRequestedInfo(
|
||||||
DISCONNECT_REASON_UNDERLYING_NETWORK_LOST));
|
DISCONNECT_REASON_UNDERLYING_NETWORK_LOST, false /* shouldQuit */));
|
||||||
mDisconnectRequestAlarm =
|
mDisconnectRequestAlarm =
|
||||||
createScheduledAlarm(
|
createScheduledAlarm(
|
||||||
DISCONNECT_REQUEST_ALARM,
|
DISCONNECT_REQUEST_ALARM,
|
||||||
@@ -909,7 +920,8 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
// Cancel any existing disconnect due to previous loss of underlying network
|
// Cancel any existing disconnect due to previous loss of underlying network
|
||||||
removeEqualMessages(
|
removeEqualMessages(
|
||||||
EVENT_DISCONNECT_REQUESTED,
|
EVENT_DISCONNECT_REQUESTED,
|
||||||
new EventDisconnectRequestedInfo(DISCONNECT_REASON_UNDERLYING_NETWORK_LOST));
|
new EventDisconnectRequestedInfo(
|
||||||
|
DISCONNECT_REASON_UNDERLYING_NETWORK_LOST, false /* shouldQuit */));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setRetryTimeoutAlarm(long delay) {
|
private void setRetryTimeoutAlarm(long delay) {
|
||||||
@@ -1041,11 +1053,8 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
enterState();
|
enterState();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Slog.wtf(TAG, "Uncaught exception", e);
|
Slog.wtf(TAG, "Uncaught exception", e);
|
||||||
sendMessageAndAcquireWakeLock(
|
sendDisconnectRequestedAndAcquireWakelock(
|
||||||
EVENT_DISCONNECT_REQUESTED,
|
DISCONNECT_REASON_INTERNAL_ERROR + e.toString(), true /* shouldQuit */);
|
||||||
TOKEN_ALL,
|
|
||||||
new EventDisconnectRequestedInfo(
|
|
||||||
DISCONNECT_REASON_INTERNAL_ERROR + e.toString()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1083,11 +1092,8 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
processStateMsg(msg);
|
processStateMsg(msg);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Slog.wtf(TAG, "Uncaught exception", e);
|
Slog.wtf(TAG, "Uncaught exception", e);
|
||||||
sendMessageAndAcquireWakeLock(
|
sendDisconnectRequestedAndAcquireWakelock(
|
||||||
EVENT_DISCONNECT_REQUESTED,
|
DISCONNECT_REASON_INTERNAL_ERROR + e.toString(), true /* shouldQuit */);
|
||||||
TOKEN_ALL,
|
|
||||||
new EventDisconnectRequestedInfo(
|
|
||||||
DISCONNECT_REASON_INTERNAL_ERROR + e.toString()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to release the WakeLock - only possible if the Handler queue is empty
|
// Attempt to release the WakeLock - only possible if the Handler queue is empty
|
||||||
@@ -1104,11 +1110,8 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
exitState();
|
exitState();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Slog.wtf(TAG, "Uncaught exception", e);
|
Slog.wtf(TAG, "Uncaught exception", e);
|
||||||
sendMessageAndAcquireWakeLock(
|
sendDisconnectRequestedAndAcquireWakelock(
|
||||||
EVENT_DISCONNECT_REQUESTED,
|
DISCONNECT_REASON_INTERNAL_ERROR + e.toString(), true /* shouldQuit */);
|
||||||
TOKEN_ALL,
|
|
||||||
new EventDisconnectRequestedInfo(
|
|
||||||
DISCONNECT_REASON_INTERNAL_ERROR + e.toString()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1141,11 +1144,11 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void handleDisconnectRequested(String msg) {
|
protected void handleDisconnectRequested(EventDisconnectRequestedInfo info) {
|
||||||
// TODO(b/180526152): notify VcnStatusCallback for Network loss
|
// TODO(b/180526152): notify VcnStatusCallback for Network loss
|
||||||
|
|
||||||
Slog.v(TAG, "Tearing down. Cause: " + msg);
|
Slog.v(TAG, "Tearing down. Cause: " + info.reason);
|
||||||
mIsRunning = false;
|
mIsQuitting = info.shouldQuit;
|
||||||
|
|
||||||
teardownNetwork();
|
teardownNetwork();
|
||||||
|
|
||||||
@@ -1177,7 +1180,7 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
private class DisconnectedState extends BaseState {
|
private class DisconnectedState extends BaseState {
|
||||||
@Override
|
@Override
|
||||||
protected void enterState() {
|
protected void enterState() {
|
||||||
if (!mIsRunning) {
|
if (mIsQuitting) {
|
||||||
quitNow(); // Ignore all queued events; cleanup is complete.
|
quitNow(); // Ignore all queued events; cleanup is complete.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1200,9 +1203,11 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EVENT_DISCONNECT_REQUESTED:
|
case EVENT_DISCONNECT_REQUESTED:
|
||||||
mIsRunning = false;
|
if (((EventDisconnectRequestedInfo) msg.obj).shouldQuit) {
|
||||||
|
mIsQuitting = true;
|
||||||
|
|
||||||
quitNow();
|
quitNow();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logUnhandledMessage(msg);
|
logUnhandledMessage(msg);
|
||||||
@@ -1284,10 +1289,11 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case EVENT_DISCONNECT_REQUESTED:
|
case EVENT_DISCONNECT_REQUESTED:
|
||||||
|
EventDisconnectRequestedInfo info = ((EventDisconnectRequestedInfo) msg.obj);
|
||||||
|
mIsQuitting = info.shouldQuit;
|
||||||
teardownNetwork();
|
teardownNetwork();
|
||||||
|
|
||||||
String reason = ((EventDisconnectRequestedInfo) msg.obj).reason;
|
if (info.reason.equals(DISCONNECT_REASON_UNDERLYING_NETWORK_LOST)) {
|
||||||
if (reason.equals(DISCONNECT_REASON_UNDERLYING_NETWORK_LOST)) {
|
|
||||||
// TODO(b/180526152): notify VcnStatusCallback for Network loss
|
// TODO(b/180526152): notify VcnStatusCallback for Network loss
|
||||||
|
|
||||||
// Will trigger EVENT_SESSION_CLOSED immediately.
|
// Will trigger EVENT_SESSION_CLOSED immediately.
|
||||||
@@ -1300,7 +1306,7 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
case EVENT_SESSION_CLOSED:
|
case EVENT_SESSION_CLOSED:
|
||||||
mIkeSession = null;
|
mIkeSession = null;
|
||||||
|
|
||||||
if (mIsRunning && mUnderlying != null) {
|
if (!mIsQuitting && mUnderlying != null) {
|
||||||
transitionTo(mSkipRetryTimeout ? mConnectingState : mRetryTimeoutState);
|
transitionTo(mSkipRetryTimeout ? mConnectingState : mRetryTimeoutState);
|
||||||
} else {
|
} else {
|
||||||
teardownNetwork();
|
teardownNetwork();
|
||||||
@@ -1391,7 +1397,7 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
transitionTo(mConnectedState);
|
transitionTo(mConnectedState);
|
||||||
break;
|
break;
|
||||||
case EVENT_DISCONNECT_REQUESTED:
|
case EVENT_DISCONNECT_REQUESTED:
|
||||||
handleDisconnectRequested(((EventDisconnectRequestedInfo) msg.obj).reason);
|
handleDisconnectRequested((EventDisconnectRequestedInfo) msg.obj);
|
||||||
break;
|
break;
|
||||||
case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED:
|
case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED:
|
||||||
mGatewayStatusCallback.onEnteredSafeMode();
|
mGatewayStatusCallback.onEnteredSafeMode();
|
||||||
@@ -1438,6 +1444,7 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
mVcnContext.getVcnNetworkProvider()) {
|
mVcnContext.getVcnNetworkProvider()) {
|
||||||
@Override
|
@Override
|
||||||
public void unwanted() {
|
public void unwanted() {
|
||||||
|
Slog.d(TAG, "NetworkAgent was unwanted");
|
||||||
teardownAsynchronously();
|
teardownAsynchronously();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1471,7 +1478,7 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
@NonNull IpSecTransform transform,
|
@NonNull IpSecTransform transform,
|
||||||
int direction) {
|
int direction) {
|
||||||
try {
|
try {
|
||||||
// TODO(b/180163196): Set underlying network of tunnel interface
|
tunnelIface.setUnderlyingNetwork(underlyingNetwork);
|
||||||
|
|
||||||
// Transforms do not need to be persisted; the IkeSession will keep them alive
|
// Transforms do not need to be persisted; the IkeSession will keep them alive
|
||||||
mIpSecManager.applyTunnelModeTransform(tunnelIface, direction, transform);
|
mIpSecManager.applyTunnelModeTransform(tunnelIface, direction, transform);
|
||||||
@@ -1577,7 +1584,7 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
setupInterfaceAndNetworkAgent(mCurrentToken, mTunnelIface, mChildConfig);
|
setupInterfaceAndNetworkAgent(mCurrentToken, mTunnelIface, mChildConfig);
|
||||||
break;
|
break;
|
||||||
case EVENT_DISCONNECT_REQUESTED:
|
case EVENT_DISCONNECT_REQUESTED:
|
||||||
handleDisconnectRequested(((EventDisconnectRequestedInfo) msg.obj).reason);
|
handleDisconnectRequested((EventDisconnectRequestedInfo) msg.obj);
|
||||||
break;
|
break;
|
||||||
case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED:
|
case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED:
|
||||||
mGatewayStatusCallback.onEnteredSafeMode();
|
mGatewayStatusCallback.onEnteredSafeMode();
|
||||||
@@ -1682,7 +1689,7 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
transitionTo(mConnectingState);
|
transitionTo(mConnectingState);
|
||||||
break;
|
break;
|
||||||
case EVENT_DISCONNECT_REQUESTED:
|
case EVENT_DISCONNECT_REQUESTED:
|
||||||
handleDisconnectRequested(((EventDisconnectRequestedInfo) msg.obj).reason);
|
handleDisconnectRequested((EventDisconnectRequestedInfo) msg.obj);
|
||||||
break;
|
break;
|
||||||
case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED:
|
case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED:
|
||||||
mGatewayStatusCallback.onEnteredSafeMode();
|
mGatewayStatusCallback.onEnteredSafeMode();
|
||||||
@@ -1905,13 +1912,13 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
boolean isRunning() {
|
boolean isQuitting() {
|
||||||
return mIsRunning;
|
return mIsQuitting;
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
void setIsRunning(boolean isRunning) {
|
void setIsQuitting(boolean isQuitting) {
|
||||||
mIsRunning = isRunning;
|
mIsQuitting = isQuitting;
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
@@ -1924,6 +1931,14 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
mIkeSession = session;
|
mIkeSession = session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
|
void sendDisconnectRequestedAndAcquireWakelock(String reason, boolean shouldQuit) {
|
||||||
|
sendMessageAndAcquireWakeLock(
|
||||||
|
EVENT_DISCONNECT_REQUESTED,
|
||||||
|
TOKEN_ALL,
|
||||||
|
new EventDisconnectRequestedInfo(reason, shouldQuit));
|
||||||
|
}
|
||||||
|
|
||||||
private IkeSessionParams buildIkeParams() {
|
private IkeSessionParams buildIkeParams() {
|
||||||
// TODO: Implement this once IkeSessionParams is persisted
|
// TODO: Implement this once IkeSessionParams is persisted
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -67,9 +67,7 @@ public class VcnNetworkProvider extends NetworkProvider {
|
|||||||
mListeners.add(listener);
|
mListeners.add(listener);
|
||||||
|
|
||||||
// Send listener all cached requests
|
// Send listener all cached requests
|
||||||
for (NetworkRequestEntry entry : mRequests.values()) {
|
resendAllRequests(listener);
|
||||||
notifyListenerForEvent(listener, entry);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Unregisters the specified listener from receiving future NetworkRequests. */
|
/** Unregisters the specified listener from receiving future NetworkRequests. */
|
||||||
@@ -78,6 +76,14 @@ public class VcnNetworkProvider extends NetworkProvider {
|
|||||||
mListeners.remove(listener);
|
mListeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Sends all cached NetworkRequest(s) to the specified listener. */
|
||||||
|
@VisibleForTesting(visibility = Visibility.PACKAGE)
|
||||||
|
public void resendAllRequests(@NonNull NetworkRequestListener listener) {
|
||||||
|
for (NetworkRequestEntry entry : mRequests.values()) {
|
||||||
|
notifyListenerForEvent(listener, entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void notifyListenerForEvent(
|
private void notifyListenerForEvent(
|
||||||
@NonNull NetworkRequestListener listener, @NonNull NetworkRequestEntry entry) {
|
@NonNull NetworkRequestListener listener, @NonNull NetworkRequestEntry entry) {
|
||||||
listener.onNetworkRequested(entry.mRequest, entry.mScore, entry.mProviderId);
|
listener.onNetworkRequested(entry.mRequest, entry.mScore, entry.mProviderId);
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import static org.mockito.Matchers.eq;
|
|||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
|
|
||||||
@@ -143,11 +144,18 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
|
|||||||
.onIpSecTransformsMigrated(makeDummyIpSecTransform(), makeDummyIpSecTransform());
|
.onIpSecTransformsMigrated(makeDummyIpSecTransform(), makeDummyIpSecTransform());
|
||||||
mTestLooper.dispatchAll();
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
verify(mIpSecSvc, times(2))
|
||||||
|
.setNetworkForTunnelInterface(
|
||||||
|
eq(TEST_IPSEC_TUNNEL_RESOURCE_ID),
|
||||||
|
eq(TEST_UNDERLYING_NETWORK_RECORD_1.network),
|
||||||
|
any());
|
||||||
|
|
||||||
for (int direction : new int[] {DIRECTION_IN, DIRECTION_OUT}) {
|
for (int direction : new int[] {DIRECTION_IN, DIRECTION_OUT}) {
|
||||||
verify(mIpSecSvc)
|
verify(mIpSecSvc)
|
||||||
.applyTunnelModeTransform(
|
.applyTunnelModeTransform(
|
||||||
eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(direction), anyInt(), any());
|
eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(direction), anyInt(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState());
|
assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,4 +298,22 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
|
|||||||
verifyIkeSessionClosedExceptionalltyNotifiesStatusCallback(
|
verifyIkeSessionClosedExceptionalltyNotifiesStatusCallback(
|
||||||
new TemporaryFailureException("vcn test"), VCN_ERROR_CODE_INTERNAL_ERROR);
|
new TemporaryFailureException("vcn test"), VCN_ERROR_CODE_INTERNAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTeardown() throws Exception {
|
||||||
|
mGatewayConnection.teardownAsynchronously();
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState());
|
||||||
|
assertTrue(mGatewayConnection.isQuitting());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNonTeardownDisconnectRequest() throws Exception {
|
||||||
|
mGatewayConnection.sendDisconnectRequestedAndAcquireWakelock("TEST", false);
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState());
|
||||||
|
assertFalse(mGatewayConnection.isQuitting());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ package com.android.server.vcn;
|
|||||||
import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession;
|
import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.Matchers.any;
|
import static org.mockito.Matchers.any;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
@@ -111,4 +113,22 @@ public class VcnGatewayConnectionConnectingStateTest extends VcnGatewayConnectio
|
|||||||
public void testSafeModeTimeoutNotifiesCallback() {
|
public void testSafeModeTimeoutNotifiesCallback() {
|
||||||
verifySafeModeTimeoutNotifiesCallback(mGatewayConnection.mConnectingState);
|
verifySafeModeTimeoutNotifiesCallback(mGatewayConnection.mConnectingState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTeardown() throws Exception {
|
||||||
|
mGatewayConnection.teardownAsynchronously();
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState());
|
||||||
|
assertTrue(mGatewayConnection.isQuitting());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNonTeardownDisconnectRequest() throws Exception {
|
||||||
|
mGatewayConnection.sendDisconnectRequestedAndAcquireWakelock("TEST", false);
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState());
|
||||||
|
assertFalse(mGatewayConnection.isQuitting());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,9 +21,12 @@ import static android.net.IpSecManager.IpSecTunnelInterface;
|
|||||||
import static com.android.server.vcn.VcnGatewayConnection.DUMMY_ADDR;
|
import static com.android.server.vcn.VcnGatewayConnection.DUMMY_ADDR;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import android.net.IpSecManager;
|
import android.net.IpSecManager;
|
||||||
@@ -54,7 +57,7 @@ public class VcnGatewayConnectionDisconnectedStateTest extends VcnGatewayConnect
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEnterWhileNotRunningTriggersQuit() throws Exception {
|
public void testEnterWhileQuittingTriggersQuit() throws Exception {
|
||||||
final VcnGatewayConnection vgc =
|
final VcnGatewayConnection vgc =
|
||||||
new VcnGatewayConnection(
|
new VcnGatewayConnection(
|
||||||
mVcnContext,
|
mVcnContext,
|
||||||
@@ -64,7 +67,7 @@ public class VcnGatewayConnectionDisconnectedStateTest extends VcnGatewayConnect
|
|||||||
mGatewayStatusCallback,
|
mGatewayStatusCallback,
|
||||||
mDeps);
|
mDeps);
|
||||||
|
|
||||||
vgc.setIsRunning(false);
|
vgc.setIsQuitting(true);
|
||||||
vgc.transitionTo(vgc.mDisconnectedState);
|
vgc.transitionTo(vgc.mDisconnectedState);
|
||||||
mTestLooper.dispatchAll();
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
@@ -101,5 +104,18 @@ public class VcnGatewayConnectionDisconnectedStateTest extends VcnGatewayConnect
|
|||||||
assertNull(mGatewayConnection.getCurrentState());
|
assertNull(mGatewayConnection.getCurrentState());
|
||||||
verify(mIpSecSvc).deleteTunnelInterface(eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), any());
|
verify(mIpSecSvc).deleteTunnelInterface(eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), any());
|
||||||
verifySafeModeTimeoutAlarmAndGetCallback(true /* expectCanceled */);
|
verifySafeModeTimeoutAlarmAndGetCallback(true /* expectCanceled */);
|
||||||
|
assertTrue(mGatewayConnection.isQuitting());
|
||||||
|
verify(mGatewayStatusCallback).onQuit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNonTeardownDisconnectRequest() throws Exception {
|
||||||
|
mGatewayConnection.sendDisconnectRequestedAndAcquireWakelock("TEST", false);
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
assertEquals(mGatewayConnection.mDisconnectedState, mGatewayConnection.getCurrentState());
|
||||||
|
assertFalse(mGatewayConnection.isQuitting());
|
||||||
|
verify(mGatewayStatusCallback, never()).onQuit();
|
||||||
|
// No safe mode timer changes expected.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ package com.android.server.vcn;
|
|||||||
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
@@ -79,10 +81,20 @@ public class VcnGatewayConnectionDisconnectingStateTest extends VcnGatewayConnec
|
|||||||
// Should do nothing; already tearing down.
|
// Should do nothing; already tearing down.
|
||||||
assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState());
|
assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState());
|
||||||
verifyTeardownTimeoutAlarmAndGetCallback(false /* expectCanceled */);
|
verifyTeardownTimeoutAlarmAndGetCallback(false /* expectCanceled */);
|
||||||
|
assertTrue(mGatewayConnection.isQuitting());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSafeModeTimeoutNotifiesCallback() {
|
public void testSafeModeTimeoutNotifiesCallback() {
|
||||||
verifySafeModeTimeoutNotifiesCallback(mGatewayConnection.mDisconnectingState);
|
verifySafeModeTimeoutNotifiesCallback(mGatewayConnection.mDisconnectingState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNonTeardownDisconnectRequest() throws Exception {
|
||||||
|
mGatewayConnection.sendDisconnectRequestedAndAcquireWakelock("TEST", false);
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState());
|
||||||
|
assertFalse(mGatewayConnection.isQuitting());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,9 @@
|
|||||||
package com.android.server.vcn;
|
package com.android.server.vcn;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
@@ -96,4 +99,22 @@ public class VcnGatewayConnectionRetryTimeoutStateTest extends VcnGatewayConnect
|
|||||||
public void testSafeModeTimeoutNotifiesCallback() {
|
public void testSafeModeTimeoutNotifiesCallback() {
|
||||||
verifySafeModeTimeoutNotifiesCallback(mGatewayConnection.mRetryTimeoutState);
|
verifySafeModeTimeoutNotifiesCallback(mGatewayConnection.mRetryTimeoutState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTeardownDisconnectRequest() throws Exception {
|
||||||
|
mGatewayConnection.teardownAsynchronously();
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
assertNull(mGatewayConnection.getCurrentState());
|
||||||
|
assertTrue(mGatewayConnection.isQuitting());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNonTeardownDisconnectRequest() throws Exception {
|
||||||
|
mGatewayConnection.sendDisconnectRequestedAndAcquireWakelock("TEST", false);
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
assertEquals(mGatewayConnection.mDisconnectedState, mGatewayConnection.getCurrentState());
|
||||||
|
assertFalse(mGatewayConnection.isQuitting());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
package com.android.server.vcn;
|
package com.android.server.vcn;
|
||||||
|
|
||||||
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
|
||||||
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
|
||||||
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.mockito.Matchers.any;
|
import static org.mockito.Matchers.any;
|
||||||
@@ -33,6 +37,7 @@ import android.net.vcn.VcnGatewayConnectionConfig;
|
|||||||
import android.net.vcn.VcnGatewayConnectionConfigTest;
|
import android.net.vcn.VcnGatewayConnectionConfigTest;
|
||||||
import android.os.ParcelUuid;
|
import android.os.ParcelUuid;
|
||||||
import android.os.test.TestLooper;
|
import android.os.test.TestLooper;
|
||||||
|
import android.util.ArraySet;
|
||||||
|
|
||||||
import com.android.server.VcnManagementService.VcnCallback;
|
import com.android.server.VcnManagementService.VcnCallback;
|
||||||
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
||||||
@@ -51,6 +56,11 @@ public class VcnTest {
|
|||||||
private static final ParcelUuid TEST_SUB_GROUP = new ParcelUuid(new UUID(0, 0));
|
private static final ParcelUuid TEST_SUB_GROUP = new ParcelUuid(new UUID(0, 0));
|
||||||
private static final int NETWORK_SCORE = 0;
|
private static final int NETWORK_SCORE = 0;
|
||||||
private static final int PROVIDER_ID = 5;
|
private static final int PROVIDER_ID = 5;
|
||||||
|
private static final int[][] TEST_CAPS =
|
||||||
|
new int[][] {
|
||||||
|
new int[] {NET_CAPABILITY_INTERNET, NET_CAPABILITY_MMS},
|
||||||
|
new int[] {NET_CAPABILITY_DUN}
|
||||||
|
};
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private VcnContext mVcnContext;
|
private VcnContext mVcnContext;
|
||||||
@@ -91,13 +101,12 @@ public class VcnTest {
|
|||||||
mGatewayStatusCallbackCaptor = ArgumentCaptor.forClass(VcnGatewayStatusCallback.class);
|
mGatewayStatusCallbackCaptor = ArgumentCaptor.forClass(VcnGatewayStatusCallback.class);
|
||||||
|
|
||||||
final VcnConfig.Builder configBuilder = new VcnConfig.Builder(mContext);
|
final VcnConfig.Builder configBuilder = new VcnConfig.Builder(mContext);
|
||||||
for (final int capability : VcnGatewayConnectionConfigTest.EXPOSED_CAPS) {
|
for (final int[] caps : TEST_CAPS) {
|
||||||
configBuilder.addGatewayConnectionConfig(
|
configBuilder.addGatewayConnectionConfig(
|
||||||
VcnGatewayConnectionConfigTest.buildTestConfigWithExposedCaps(capability));
|
VcnGatewayConnectionConfigTest.buildTestConfigWithExposedCaps(caps));
|
||||||
}
|
}
|
||||||
configBuilder.addGatewayConnectionConfig(VcnGatewayConnectionConfigTest.buildTestConfig());
|
|
||||||
mConfig = configBuilder.build();
|
|
||||||
|
|
||||||
|
mConfig = configBuilder.build();
|
||||||
mVcn =
|
mVcn =
|
||||||
new Vcn(
|
new Vcn(
|
||||||
mVcnContext,
|
mVcnContext,
|
||||||
@@ -130,8 +139,7 @@ public class VcnTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSubscriptionSnapshotUpdatesVcnGatewayConnections() {
|
public void testSubscriptionSnapshotUpdatesVcnGatewayConnections() {
|
||||||
final NetworkRequestListener requestListener = verifyAndGetRequestListener();
|
final NetworkRequestListener requestListener = verifyAndGetRequestListener();
|
||||||
startVcnGatewayWithCapabilities(
|
startVcnGatewayWithCapabilities(requestListener, TEST_CAPS[0]);
|
||||||
requestListener, VcnGatewayConnectionConfigTest.EXPOSED_CAPS);
|
|
||||||
|
|
||||||
final Set<VcnGatewayConnection> gatewayConnections = mVcn.getVcnGatewayConnections();
|
final Set<VcnGatewayConnection> gatewayConnections = mVcn.getVcnGatewayConnections();
|
||||||
assertFalse(gatewayConnections.isEmpty());
|
assertFalse(gatewayConnections.isEmpty());
|
||||||
@@ -153,10 +161,19 @@ public class VcnTest {
|
|||||||
for (final int capability : VcnGatewayConnectionConfigTest.EXPOSED_CAPS) {
|
for (final int capability : VcnGatewayConnectionConfigTest.EXPOSED_CAPS) {
|
||||||
startVcnGatewayWithCapabilities(requestListener, capability);
|
startVcnGatewayWithCapabilities(requestListener, capability);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Each Capability in EXPOSED_CAPS was split into a separate VcnGatewayConnection in #setUp.
|
private void triggerVcnRequestListeners(NetworkRequestListener requestListener) {
|
||||||
// Expect one VcnGatewayConnection per capability.
|
for (final int[] caps : TEST_CAPS) {
|
||||||
final int numExpectedGateways = VcnGatewayConnectionConfigTest.EXPOSED_CAPS.length;
|
startVcnGatewayWithCapabilities(requestListener, caps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<VcnGatewayConnection> startGatewaysAndGetGatewayConnections(
|
||||||
|
NetworkRequestListener requestListener) {
|
||||||
|
triggerVcnRequestListeners(requestListener);
|
||||||
|
|
||||||
|
final int numExpectedGateways = TEST_CAPS.length;
|
||||||
|
|
||||||
final Set<VcnGatewayConnection> gatewayConnections = mVcn.getVcnGatewayConnections();
|
final Set<VcnGatewayConnection> gatewayConnections = mVcn.getVcnGatewayConnections();
|
||||||
assertEquals(numExpectedGateways, gatewayConnections.size());
|
assertEquals(numExpectedGateways, gatewayConnections.size());
|
||||||
@@ -168,7 +185,16 @@ public class VcnTest {
|
|||||||
any(),
|
any(),
|
||||||
mGatewayStatusCallbackCaptor.capture());
|
mGatewayStatusCallbackCaptor.capture());
|
||||||
|
|
||||||
// Doesn't matter which callback this gets - any Gateway entering safe mode should shut down
|
return gatewayConnections;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGatewayEnteringSafemodeNotifiesVcn() {
|
||||||
|
final NetworkRequestListener requestListener = verifyAndGetRequestListener();
|
||||||
|
final Set<VcnGatewayConnection> gatewayConnections =
|
||||||
|
startGatewaysAndGetGatewayConnections(requestListener);
|
||||||
|
|
||||||
|
// Doesn't matter which callback this gets - any Gateway entering Safemode should shut down
|
||||||
// all Gateways
|
// all Gateways
|
||||||
final VcnGatewayStatusCallback statusCallback = mGatewayStatusCallbackCaptor.getValue();
|
final VcnGatewayStatusCallback statusCallback = mGatewayStatusCallbackCaptor.getValue();
|
||||||
statusCallback.onEnteredSafeMode();
|
statusCallback.onEnteredSafeMode();
|
||||||
@@ -181,4 +207,31 @@ public class VcnTest {
|
|||||||
verify(mVcnNetworkProvider).unregisterListener(requestListener);
|
verify(mVcnNetworkProvider).unregisterListener(requestListener);
|
||||||
verify(mVcnCallback).onEnteredSafeMode();
|
verify(mVcnCallback).onEnteredSafeMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGatewayQuit() {
|
||||||
|
final NetworkRequestListener requestListener = verifyAndGetRequestListener();
|
||||||
|
final Set<VcnGatewayConnection> gatewayConnections =
|
||||||
|
new ArraySet<>(startGatewaysAndGetGatewayConnections(requestListener));
|
||||||
|
|
||||||
|
final VcnGatewayStatusCallback statusCallback = mGatewayStatusCallbackCaptor.getValue();
|
||||||
|
statusCallback.onQuit();
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
// Verify that the VCN requests the networkRequests be resent
|
||||||
|
assertEquals(1, mVcn.getVcnGatewayConnections().size());
|
||||||
|
verify(mVcnNetworkProvider).resendAllRequests(requestListener);
|
||||||
|
|
||||||
|
// Verify that the VcnGatewayConnection is restarted
|
||||||
|
triggerVcnRequestListeners(requestListener);
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
assertEquals(2, mVcn.getVcnGatewayConnections().size());
|
||||||
|
verify(mDeps, times(gatewayConnections.size() + 1))
|
||||||
|
.newVcnGatewayConnection(
|
||||||
|
eq(mVcnContext),
|
||||||
|
eq(TEST_SUB_GROUP),
|
||||||
|
eq(mSubscriptionSnapshot),
|
||||||
|
any(),
|
||||||
|
mGatewayStatusCallbackCaptor.capture());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user