Merge changes Icf32cb46,I43434c80,I59dc46dc,I7df3f14b,I50f2c0e9 am: e253ce3463 am: 9083a4cf04
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1664800 Change-Id: Ide383ab76488b6d60f9349bfa9efd5264cea167c
This commit is contained in:
@@ -542,16 +542,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
|
|||||||
|
|
||||||
if (mVcns.containsKey(subscriptionGroup)) {
|
if (mVcns.containsKey(subscriptionGroup)) {
|
||||||
final Vcn vcn = mVcns.get(subscriptionGroup);
|
final Vcn vcn = mVcns.get(subscriptionGroup);
|
||||||
final int status = vcn.getStatus();
|
|
||||||
vcn.updateConfig(config);
|
vcn.updateConfig(config);
|
||||||
|
|
||||||
// TODO(b/183174340): Remove this once opportunistic-safe-mode is supported
|
|
||||||
// Only notify VcnStatusCallbacks if this VCN was previously in Safe Mode
|
|
||||||
if (status == VCN_STATUS_CODE_SAFE_MODE) {
|
|
||||||
// TODO(b/181789060): invoke asynchronously after Vcn notifies through VcnCallback
|
|
||||||
notifyAllPermissionedStatusCallbacksLocked(
|
|
||||||
subscriptionGroup, VCN_STATUS_CODE_ACTIVE);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
startVcnLocked(subscriptionGroup, config);
|
startVcnLocked(subscriptionGroup, config);
|
||||||
}
|
}
|
||||||
@@ -941,8 +932,8 @@ public class VcnManagementService extends IVcnManagementService.Stub {
|
|||||||
// TODO(b/180452282): Make name more generic and implement directly with VcnManagementService
|
// TODO(b/180452282): Make name more generic and implement directly with VcnManagementService
|
||||||
/** Callback for Vcn signals sent up to VcnManagementService. */
|
/** Callback for Vcn signals sent up to VcnManagementService. */
|
||||||
public interface VcnCallback {
|
public interface VcnCallback {
|
||||||
/** Called by a Vcn to signal that it has entered safe mode. */
|
/** Called by a Vcn to signal that its safe mode status has changed. */
|
||||||
void onEnteredSafeMode();
|
void onSafeModeStatusChanged(boolean isInSafeMode);
|
||||||
|
|
||||||
/** Called by a Vcn to signal that an error occurred. */
|
/** Called by a Vcn to signal that an error occurred. */
|
||||||
void onGatewayConnectionError(
|
void onGatewayConnectionError(
|
||||||
@@ -1004,15 +995,18 @@ public class VcnManagementService extends IVcnManagementService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnteredSafeMode() {
|
public void onSafeModeStatusChanged(boolean isInSafeMode) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
// Ignore if this subscription group doesn't exist anymore
|
// Ignore if this subscription group doesn't exist anymore
|
||||||
if (!mVcns.containsKey(mSubGroup)) {
|
if (!mVcns.containsKey(mSubGroup)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final int status =
|
||||||
|
isInSafeMode ? VCN_STATUS_CODE_SAFE_MODE : VCN_STATUS_CODE_ACTIVE;
|
||||||
|
|
||||||
notifyAllPolicyListenersLocked();
|
notifyAllPolicyListenersLocked();
|
||||||
notifyAllPermissionedStatusCallbacksLocked(mSubGroup, VCN_STATUS_CODE_SAFE_MODE);
|
notifyAllPermissionedStatusCallbacksLocked(mSubGroup, status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package com.android.server.vcn;
|
package com.android.server.vcn;
|
||||||
|
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
|
||||||
|
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
||||||
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
|
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
|
||||||
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_INACTIVE;
|
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_INACTIVE;
|
||||||
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
|
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
|
||||||
@@ -96,17 +97,21 @@ public class Vcn extends Handler {
|
|||||||
*/
|
*/
|
||||||
private static final int MSG_EVENT_GATEWAY_CONNECTION_QUIT = MSG_EVENT_BASE + 3;
|
private static final int MSG_EVENT_GATEWAY_CONNECTION_QUIT = MSG_EVENT_BASE + 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers reevaluation of safe mode conditions.
|
||||||
|
*
|
||||||
|
* <p>Upon entering safe mode, the VCN will only provide gateway connections opportunistically,
|
||||||
|
* leaving the underlying networks marked as NOT_VCN_MANAGED.
|
||||||
|
*
|
||||||
|
* <p>Any VcnGatewayConnection in safe mode will result in the entire Vcn instance being put
|
||||||
|
* into safe mode. Upon receiving this message, the Vcn MUST query all VcnGatewayConnections to
|
||||||
|
* determine if any are in safe mode.
|
||||||
|
*/
|
||||||
|
private static final int MSG_EVENT_SAFE_MODE_STATE_CHANGED = MSG_EVENT_BASE + 4;
|
||||||
|
|
||||||
/** 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;
|
||||||
|
|
||||||
/**
|
|
||||||
* Causes this VCN to immediately enter safe mode.
|
|
||||||
*
|
|
||||||
* <p>Upon entering safe mode, the VCN will unregister its RequestListener, tear down all of its
|
|
||||||
* VcnGatewayConnections, and notify VcnManagementService that it is in safe mode.
|
|
||||||
*/
|
|
||||||
private static final int MSG_CMD_ENTER_SAFE_MODE = MSG_CMD_BASE + 1;
|
|
||||||
|
|
||||||
@NonNull private final VcnContext mVcnContext;
|
@NonNull private final VcnContext mVcnContext;
|
||||||
@NonNull private final ParcelUuid mSubscriptionGroup;
|
@NonNull private final ParcelUuid mSubscriptionGroup;
|
||||||
@NonNull private final Dependencies mDeps;
|
@NonNull private final Dependencies mDeps;
|
||||||
@@ -233,6 +238,11 @@ public class Vcn extends Handler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(@NonNull Message msg) {
|
public void handleMessage(@NonNull Message msg) {
|
||||||
|
if (mCurrentStatus != VCN_STATUS_CODE_ACTIVE
|
||||||
|
&& mCurrentStatus != VCN_STATUS_CODE_SAFE_MODE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
case MSG_EVENT_CONFIG_UPDATED:
|
case MSG_EVENT_CONFIG_UPDATED:
|
||||||
handleConfigUpdated((VcnConfig) msg.obj);
|
handleConfigUpdated((VcnConfig) msg.obj);
|
||||||
@@ -246,12 +256,12 @@ public class Vcn extends Handler {
|
|||||||
case MSG_EVENT_GATEWAY_CONNECTION_QUIT:
|
case MSG_EVENT_GATEWAY_CONNECTION_QUIT:
|
||||||
handleGatewayConnectionQuit((VcnGatewayConnectionConfig) msg.obj);
|
handleGatewayConnectionQuit((VcnGatewayConnectionConfig) msg.obj);
|
||||||
break;
|
break;
|
||||||
|
case MSG_EVENT_SAFE_MODE_STATE_CHANGED:
|
||||||
|
handleSafeModeStatusChanged();
|
||||||
|
break;
|
||||||
case MSG_CMD_TEARDOWN:
|
case MSG_CMD_TEARDOWN:
|
||||||
handleTeardown();
|
handleTeardown();
|
||||||
break;
|
break;
|
||||||
case MSG_CMD_ENTER_SAFE_MODE:
|
|
||||||
handleEnterSafeMode();
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
Slog.wtf(getLogTag(), "Unknown msg.what: " + msg.what);
|
Slog.wtf(getLogTag(), "Unknown msg.what: " + msg.what);
|
||||||
}
|
}
|
||||||
@@ -263,40 +273,28 @@ public class Vcn extends Handler {
|
|||||||
|
|
||||||
mConfig = config;
|
mConfig = config;
|
||||||
|
|
||||||
// TODO(b/183174340): Remove this once opportunistic safe mode is supported.
|
// Teardown any GatewayConnections whose configs have been removed and get all current
|
||||||
if (mCurrentStatus == VCN_STATUS_CODE_ACTIVE) {
|
// requests
|
||||||
// VCN is already active - teardown any GatewayConnections whose configs have been
|
for (final Entry<VcnGatewayConnectionConfig, VcnGatewayConnection> entry :
|
||||||
// removed and get all current requests
|
mVcnGatewayConnections.entrySet()) {
|
||||||
for (final Entry<VcnGatewayConnectionConfig, VcnGatewayConnection> entry :
|
final VcnGatewayConnectionConfig gatewayConnectionConfig = entry.getKey();
|
||||||
mVcnGatewayConnections.entrySet()) {
|
final VcnGatewayConnection gatewayConnection = entry.getValue();
|
||||||
final VcnGatewayConnectionConfig gatewayConnectionConfig = entry.getKey();
|
|
||||||
final VcnGatewayConnection gatewayConnection = entry.getValue();
|
|
||||||
|
|
||||||
// GatewayConnectionConfigs must match exactly (otherwise authentication or
|
// GatewayConnectionConfigs must match exactly (otherwise authentication or
|
||||||
// connection details may have changed).
|
// connection details may have changed).
|
||||||
if (!mConfig.getGatewayConnectionConfigs().contains(gatewayConnectionConfig)) {
|
if (!mConfig.getGatewayConnectionConfigs().contains(gatewayConnectionConfig)) {
|
||||||
if (gatewayConnection == null) {
|
if (gatewayConnection == null) {
|
||||||
Slog.wtf(
|
Slog.wtf(
|
||||||
getLogTag(),
|
getLogTag(), "Found gatewayConnectionConfig without GatewayConnection");
|
||||||
"Found gatewayConnectionConfig without GatewayConnection");
|
} else {
|
||||||
} else {
|
gatewayConnection.teardownAsynchronously();
|
||||||
gatewayConnection.teardownAsynchronously();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trigger a re-evaluation of all NetworkRequests (to make sure any that can be
|
|
||||||
// satisfied start a new GatewayConnection)
|
|
||||||
mVcnContext.getVcnNetworkProvider().resendAllRequests(mRequestListener);
|
|
||||||
} else if (mCurrentStatus == VCN_STATUS_CODE_SAFE_MODE) {
|
|
||||||
// If this VCN was not previously active, it is exiting Safe Mode. Re-register the
|
|
||||||
// request listener to get NetworkRequests again (and all cached requests).
|
|
||||||
mVcnContext.getVcnNetworkProvider().registerListener(mRequestListener);
|
|
||||||
} else {
|
|
||||||
// Ignored; VCN was not active; config updates ignored.
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
mCurrentStatus = VCN_STATUS_CODE_ACTIVE;
|
|
||||||
|
// 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 handleTeardown() {
|
private void handleTeardown() {
|
||||||
@@ -309,21 +307,27 @@ public class Vcn extends Handler {
|
|||||||
mCurrentStatus = VCN_STATUS_CODE_INACTIVE;
|
mCurrentStatus = VCN_STATUS_CODE_INACTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleEnterSafeMode() {
|
private void handleSafeModeStatusChanged() {
|
||||||
// TODO(b/183174340): Remove this once opportunistic-safe-mode is supported
|
boolean hasSafeModeGatewayConnection = false;
|
||||||
handleTeardown();
|
|
||||||
|
|
||||||
mCurrentStatus = VCN_STATUS_CODE_SAFE_MODE;
|
// If any VcnGatewayConnection is in safe mode, mark the entire VCN as being in safe mode
|
||||||
mVcnCallback.onEnteredSafeMode();
|
for (VcnGatewayConnection gatewayConnection : mVcnGatewayConnections.values()) {
|
||||||
|
if (gatewayConnection.isInSafeMode()) {
|
||||||
|
hasSafeModeGatewayConnection = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final int oldStatus = mCurrentStatus;
|
||||||
|
mCurrentStatus =
|
||||||
|
hasSafeModeGatewayConnection ? VCN_STATUS_CODE_SAFE_MODE : VCN_STATUS_CODE_ACTIVE;
|
||||||
|
if (oldStatus != mCurrentStatus) {
|
||||||
|
mVcnCallback.onSafeModeStatusChanged(hasSafeModeGatewayConnection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleNetworkRequested(
|
private void handleNetworkRequested(
|
||||||
@NonNull NetworkRequest request, int score, int providerId) {
|
@NonNull NetworkRequest request, int score, int providerId) {
|
||||||
if (mCurrentStatus != VCN_STATUS_CODE_ACTIVE) {
|
|
||||||
Slog.v(getLogTag(), "Received NetworkRequest while inactive. Ignore for now");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (score > getNetworkScore()) {
|
if (score > getNetworkScore()) {
|
||||||
if (VDBG) {
|
if (VDBG) {
|
||||||
Slog.v(
|
Slog.v(
|
||||||
@@ -376,25 +380,23 @@ public class Vcn extends Handler {
|
|||||||
mVcnGatewayConnections.remove(config);
|
mVcnGatewayConnections.remove(config);
|
||||||
|
|
||||||
// Trigger a re-evaluation of all NetworkRequests (to make sure any that can be satisfied
|
// Trigger a re-evaluation of all NetworkRequests (to make sure any that can be satisfied
|
||||||
// start a new GatewayConnection), but only if the Vcn is still alive
|
// start a new GatewayConnection). VCN is always alive here, courtesy of the liveness check
|
||||||
if (mCurrentStatus == VCN_STATUS_CODE_ACTIVE) {
|
// in handleMessage()
|
||||||
mVcnContext.getVcnNetworkProvider().resendAllRequests(mRequestListener);
|
mVcnContext.getVcnNetworkProvider().resendAllRequests(mRequestListener);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSubscriptionsChanged(@NonNull TelephonySubscriptionSnapshot snapshot) {
|
private void handleSubscriptionsChanged(@NonNull TelephonySubscriptionSnapshot snapshot) {
|
||||||
mLastSnapshot = snapshot;
|
mLastSnapshot = snapshot;
|
||||||
|
|
||||||
if (mCurrentStatus == VCN_STATUS_CODE_ACTIVE) {
|
for (VcnGatewayConnection gatewayConnection : mVcnGatewayConnections.values()) {
|
||||||
for (VcnGatewayConnection gatewayConnection : mVcnGatewayConnections.values()) {
|
gatewayConnection.updateSubscriptionSnapshot(mLastSnapshot);
|
||||||
gatewayConnection.updateSubscriptionSnapshot(mLastSnapshot);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isRequestSatisfiedByGatewayConnectionConfig(
|
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.addTransportType(TRANSPORT_CELLULAR);
|
||||||
builder.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
|
builder.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
|
||||||
for (int cap : config.getAllExposedCapabilities()) {
|
for (int cap : config.getAllExposedCapabilities()) {
|
||||||
builder.addCapability(cap);
|
builder.addCapability(cap);
|
||||||
@@ -418,8 +420,8 @@ public class Vcn extends Handler {
|
|||||||
/** Callback used for passing status signals from a VcnGatewayConnection to its managing Vcn. */
|
/** Callback used for passing status signals from a VcnGatewayConnection to its managing Vcn. */
|
||||||
@VisibleForTesting(visibility = Visibility.PACKAGE)
|
@VisibleForTesting(visibility = Visibility.PACKAGE)
|
||||||
public interface VcnGatewayStatusCallback {
|
public interface VcnGatewayStatusCallback {
|
||||||
/** Called by a VcnGatewayConnection to indicate that it has entered safe mode. */
|
/** Called by a VcnGatewayConnection to indicate that it's safe mode status has changed. */
|
||||||
void onEnteredSafeMode();
|
void onSafeModeStatusChanged();
|
||||||
|
|
||||||
/** Callback by a VcnGatewayConnection to indicate that an error occurred. */
|
/** Callback by a VcnGatewayConnection to indicate that an error occurred. */
|
||||||
void onGatewayConnectionError(
|
void onGatewayConnectionError(
|
||||||
@@ -445,8 +447,8 @@ public class Vcn extends Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnteredSafeMode() {
|
public void onSafeModeStatusChanged() {
|
||||||
sendMessage(obtainMessage(MSG_CMD_ENTER_SAFE_MODE));
|
sendMessage(obtainMessage(MSG_EVENT_SAFE_MODE_STATE_CHANGED));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import static com.android.server.VcnManagementService.VDBG;
|
|||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
import android.net.InetAddresses;
|
import android.net.InetAddresses;
|
||||||
import android.net.IpPrefix;
|
import android.net.IpPrefix;
|
||||||
import android.net.IpSecManager;
|
import android.net.IpSecManager;
|
||||||
@@ -44,6 +45,7 @@ import android.net.Network;
|
|||||||
import android.net.NetworkAgent;
|
import android.net.NetworkAgent;
|
||||||
import android.net.NetworkAgentConfig;
|
import android.net.NetworkAgentConfig;
|
||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
|
import android.net.NetworkProvider;
|
||||||
import android.net.RouteInfo;
|
import android.net.RouteInfo;
|
||||||
import android.net.TelephonyNetworkSpecifier;
|
import android.net.TelephonyNetworkSpecifier;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@@ -92,6 +94,7 @@ import java.util.List;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A single VCN Gateway Connection, providing a single public-facing VCN network.
|
* A single VCN Gateway Connection, providing a single public-facing VCN network.
|
||||||
@@ -503,6 +506,15 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
*/
|
*/
|
||||||
private boolean mIsQuitting = false;
|
private boolean mIsQuitting = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the VcnGatewayConnection is in safe mode.
|
||||||
|
*
|
||||||
|
* <p>Upon hitting the safe mode timeout, this will be set to {@code true}. In safe mode, this
|
||||||
|
* VcnGatewayConnection will continue attempting to connect, and if a successful connection is
|
||||||
|
* made, safe mode will be exited.
|
||||||
|
*/
|
||||||
|
private boolean mIsInSafeMode = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The token used by the primary/current/active session.
|
* The token used by the primary/current/active session.
|
||||||
*
|
*
|
||||||
@@ -562,8 +574,7 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
* <p>Set in Connected state, always @NonNull in Connected, Migrating states, @Nullable
|
* <p>Set in Connected state, always @NonNull in Connected, Migrating states, @Nullable
|
||||||
* otherwise.
|
* otherwise.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
private NetworkAgent mNetworkAgent;
|
||||||
NetworkAgent mNetworkAgent;
|
|
||||||
|
|
||||||
@Nullable private WakeupMessage mTeardownTimeoutAlarm;
|
@Nullable private WakeupMessage mTeardownTimeoutAlarm;
|
||||||
@Nullable private WakeupMessage mDisconnectRequestAlarm;
|
@Nullable private WakeupMessage mDisconnectRequestAlarm;
|
||||||
@@ -628,6 +639,14 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Queries whether this VcnGatewayConnection is in safe mode. */
|
||||||
|
public boolean isInSafeMode() {
|
||||||
|
// Accessing internal state; must only be done on looper thread.
|
||||||
|
mVcnContext.ensureRunningOnLooperThread();
|
||||||
|
|
||||||
|
return mIsInSafeMode;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronously tears down this GatewayConnection, and any resources used.
|
* Asynchronously tears down this GatewayConnection, and any resources used.
|
||||||
*
|
*
|
||||||
@@ -1162,6 +1181,15 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void handleSafeModeTimeoutExceeded() {
|
||||||
|
mSafeModeTimeoutAlarm = null;
|
||||||
|
|
||||||
|
// Connectivity for this GatewayConnection is broken; tear down the Network.
|
||||||
|
teardownNetwork();
|
||||||
|
mIsInSafeMode = true;
|
||||||
|
mGatewayStatusCallback.onSafeModeStatusChanged();
|
||||||
|
}
|
||||||
|
|
||||||
protected void logUnexpectedEvent(int what) {
|
protected void logUnexpectedEvent(int what) {
|
||||||
Slog.d(TAG, String.format(
|
Slog.d(TAG, String.format(
|
||||||
"Unexpected event code %d in state %s", what, this.getClass().getSimpleName()));
|
"Unexpected event code %d in state %s", what, this.getClass().getSimpleName()));
|
||||||
@@ -1315,8 +1343,7 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED:
|
case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED:
|
||||||
mGatewayStatusCallback.onEnteredSafeMode();
|
handleSafeModeTimeoutExceeded();
|
||||||
mSafeModeTimeoutAlarm = null;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logUnhandledMessage(msg);
|
logUnhandledMessage(msg);
|
||||||
@@ -1401,8 +1428,7 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
handleDisconnectRequested((EventDisconnectRequestedInfo) msg.obj);
|
handleDisconnectRequested((EventDisconnectRequestedInfo) msg.obj);
|
||||||
break;
|
break;
|
||||||
case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED:
|
case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED:
|
||||||
mGatewayStatusCallback.onEnteredSafeMode();
|
handleSafeModeTimeoutExceeded();
|
||||||
mSafeModeTimeoutAlarm = null;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logUnhandledMessage(msg);
|
logUnhandledMessage(msg);
|
||||||
@@ -1432,30 +1458,35 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
buildNetworkCapabilities(mConnectionConfig, mUnderlying);
|
buildNetworkCapabilities(mConnectionConfig, mUnderlying);
|
||||||
final LinkProperties lp =
|
final LinkProperties lp =
|
||||||
buildConnectedLinkProperties(mConnectionConfig, tunnelIface, childConfig);
|
buildConnectedLinkProperties(mConnectionConfig, tunnelIface, childConfig);
|
||||||
|
final NetworkAgentConfig nac =
|
||||||
|
new NetworkAgentConfig.Builder()
|
||||||
|
.setLegacyType(ConnectivityManager.TYPE_MOBILE)
|
||||||
|
.build();
|
||||||
|
|
||||||
final NetworkAgent agent =
|
final NetworkAgent agent =
|
||||||
new NetworkAgent(
|
mDeps.newNetworkAgent(
|
||||||
mVcnContext.getContext(),
|
mVcnContext,
|
||||||
mVcnContext.getLooper(),
|
|
||||||
TAG,
|
TAG,
|
||||||
caps,
|
caps,
|
||||||
lp,
|
lp,
|
||||||
Vcn.getNetworkScore(),
|
Vcn.getNetworkScore(),
|
||||||
new NetworkAgentConfig.Builder().build(),
|
nac,
|
||||||
mVcnContext.getVcnNetworkProvider()) {
|
mVcnContext.getVcnNetworkProvider(),
|
||||||
@Override
|
() -> {
|
||||||
public void onNetworkUnwanted() {
|
Slog.d(TAG, "NetworkAgent was unwanted");
|
||||||
Slog.d(TAG, "NetworkAgent was unwanted");
|
// If network agent has already been torn down, skip sending the
|
||||||
teardownAsynchronously();
|
// disconnect. Unwanted() is always called, even when networkAgents
|
||||||
}
|
// are unregistered in teardownNetwork(), so prevent duplicate
|
||||||
|
// notifications.
|
||||||
@Override
|
if (mNetworkAgent != null) {
|
||||||
public void onValidationStatus(int status, @Nullable Uri redirectUri) {
|
teardownAsynchronously();
|
||||||
if (status == NetworkAgent.VALIDATION_STATUS_VALID) {
|
}
|
||||||
clearFailedAttemptCounterAndSafeModeAlarm();
|
} /* networkUnwantedCallback */,
|
||||||
}
|
(status) -> {
|
||||||
}
|
if (status == NetworkAgent.VALIDATION_STATUS_VALID) {
|
||||||
};
|
clearFailedAttemptCounterAndSafeModeAlarm();
|
||||||
|
}
|
||||||
|
} /* validationStatusCallback */);
|
||||||
|
|
||||||
agent.register();
|
agent.register();
|
||||||
agent.markConnected();
|
agent.markConnected();
|
||||||
@@ -1469,6 +1500,11 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
// Validated connection, clear failed attempt counter
|
// Validated connection, clear failed attempt counter
|
||||||
mFailedAttempts = 0;
|
mFailedAttempts = 0;
|
||||||
cancelSafeModeAlarm();
|
cancelSafeModeAlarm();
|
||||||
|
|
||||||
|
if (mIsInSafeMode) {
|
||||||
|
mIsInSafeMode = false;
|
||||||
|
mGatewayStatusCallback.onSafeModeStatusChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void applyTransform(
|
protected void applyTransform(
|
||||||
@@ -1488,13 +1524,6 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setupInterface(
|
|
||||||
int token,
|
|
||||||
@NonNull IpSecTunnelInterface tunnelIface,
|
|
||||||
@NonNull VcnChildSessionConfiguration childConfig) {
|
|
||||||
setupInterface(token, tunnelIface, childConfig, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setupInterface(
|
protected void setupInterface(
|
||||||
int token,
|
int token,
|
||||||
@NonNull IpSecTunnelInterface tunnelIface,
|
@NonNull IpSecTunnelInterface tunnelIface,
|
||||||
@@ -1579,16 +1608,17 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
transformCreatedInfo.direction);
|
transformCreatedInfo.direction);
|
||||||
break;
|
break;
|
||||||
case EVENT_SETUP_COMPLETED:
|
case EVENT_SETUP_COMPLETED:
|
||||||
|
final VcnChildSessionConfiguration oldChildConfig = mChildConfig;
|
||||||
mChildConfig = ((EventSetupCompletedInfo) msg.obj).childSessionConfig;
|
mChildConfig = ((EventSetupCompletedInfo) msg.obj).childSessionConfig;
|
||||||
|
|
||||||
setupInterfaceAndNetworkAgent(mCurrentToken, mTunnelIface, mChildConfig);
|
setupInterfaceAndNetworkAgent(
|
||||||
|
mCurrentToken, mTunnelIface, mChildConfig, oldChildConfig);
|
||||||
break;
|
break;
|
||||||
case EVENT_DISCONNECT_REQUESTED:
|
case EVENT_DISCONNECT_REQUESTED:
|
||||||
handleDisconnectRequested((EventDisconnectRequestedInfo) msg.obj);
|
handleDisconnectRequested((EventDisconnectRequestedInfo) msg.obj);
|
||||||
break;
|
break;
|
||||||
case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED:
|
case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED:
|
||||||
mGatewayStatusCallback.onEnteredSafeMode();
|
handleSafeModeTimeoutExceeded();
|
||||||
mSafeModeTimeoutAlarm = null;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logUnhandledMessage(msg);
|
logUnhandledMessage(msg);
|
||||||
@@ -1626,8 +1656,9 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
protected void setupInterfaceAndNetworkAgent(
|
protected void setupInterfaceAndNetworkAgent(
|
||||||
int token,
|
int token,
|
||||||
@NonNull IpSecTunnelInterface tunnelIface,
|
@NonNull IpSecTunnelInterface tunnelIface,
|
||||||
@NonNull VcnChildSessionConfiguration childConfig) {
|
@NonNull VcnChildSessionConfiguration childConfig,
|
||||||
setupInterface(token, tunnelIface, childConfig);
|
@NonNull VcnChildSessionConfiguration oldChildConfig) {
|
||||||
|
setupInterface(token, tunnelIface, childConfig, oldChildConfig);
|
||||||
|
|
||||||
if (mNetworkAgent == null) {
|
if (mNetworkAgent == null) {
|
||||||
mNetworkAgent = buildNetworkAgent(tunnelIface, childConfig);
|
mNetworkAgent = buildNetworkAgent(tunnelIface, childConfig);
|
||||||
@@ -1692,8 +1723,7 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
handleDisconnectRequested((EventDisconnectRequestedInfo) msg.obj);
|
handleDisconnectRequested((EventDisconnectRequestedInfo) msg.obj);
|
||||||
break;
|
break;
|
||||||
case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED:
|
case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED:
|
||||||
mGatewayStatusCallback.onEnteredSafeMode();
|
handleSafeModeTimeoutExceeded();
|
||||||
mSafeModeTimeoutAlarm = null;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logUnhandledMessage(msg);
|
logUnhandledMessage(msg);
|
||||||
@@ -1934,6 +1964,16 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
mIkeSession = session;
|
mIkeSession = session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
|
NetworkAgent getNetworkAgent() {
|
||||||
|
return mNetworkAgent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
|
void setNetworkAgent(@Nullable NetworkAgent networkAgent) {
|
||||||
|
mNetworkAgent = networkAgent;
|
||||||
|
}
|
||||||
|
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
void sendDisconnectRequestedAndAcquireWakelock(String reason, boolean shouldQuit) {
|
void sendDisconnectRequestedAndAcquireWakelock(String reason, boolean shouldQuit) {
|
||||||
sendMessageAndAcquireWakeLock(
|
sendMessageAndAcquireWakeLock(
|
||||||
@@ -2018,6 +2058,38 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
return new WakeupMessage(vcnContext.getContext(), handler, tag, runnable);
|
return new WakeupMessage(vcnContext.getContext(), handler, tag, runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Builds a new NetworkAgent. */
|
||||||
|
public NetworkAgent newNetworkAgent(
|
||||||
|
@NonNull VcnContext vcnContext,
|
||||||
|
@NonNull String tag,
|
||||||
|
@NonNull NetworkCapabilities caps,
|
||||||
|
@NonNull LinkProperties lp,
|
||||||
|
@NonNull int score,
|
||||||
|
@NonNull NetworkAgentConfig nac,
|
||||||
|
@NonNull NetworkProvider provider,
|
||||||
|
@NonNull Runnable networkUnwantedCallback,
|
||||||
|
@NonNull Consumer<Integer> validationStatusCallback) {
|
||||||
|
return new NetworkAgent(
|
||||||
|
vcnContext.getContext(),
|
||||||
|
vcnContext.getLooper(),
|
||||||
|
tag,
|
||||||
|
caps,
|
||||||
|
lp,
|
||||||
|
score,
|
||||||
|
nac,
|
||||||
|
provider) {
|
||||||
|
@Override
|
||||||
|
public void onNetworkUnwanted() {
|
||||||
|
networkUnwantedCallback.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onValidationStatus(int status, @Nullable Uri redirectUri) {
|
||||||
|
validationStatusCallback.accept(status);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/** Gets the elapsed real time since boot, in millis. */
|
/** Gets the elapsed real time since boot, in millis. */
|
||||||
public long getElapsedRealTime() {
|
public long getElapsedRealTime() {
|
||||||
return SystemClock.elapsedRealtime();
|
return SystemClock.elapsedRealtime();
|
||||||
|
|||||||
@@ -536,17 +536,6 @@ public class VcnManagementServiceTest {
|
|||||||
verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_ACTIVE);
|
verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_ACTIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSetVcnConfigInSafeModeNotifiesStatusCallback() throws Exception {
|
|
||||||
setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_2, false /* isActive */);
|
|
||||||
mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_2, mMockStatusCallback, TEST_PACKAGE_NAME);
|
|
||||||
verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_SAFE_MODE);
|
|
||||||
|
|
||||||
mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME);
|
|
||||||
|
|
||||||
verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_ACTIVE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testClearVcnConfigRequiresNonSystemServer() throws Exception {
|
public void testClearVcnConfigRequiresNonSystemServer() throws Exception {
|
||||||
doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid();
|
doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid();
|
||||||
@@ -902,7 +891,9 @@ public class VcnManagementServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void triggerVcnSafeMode(
|
private void triggerVcnSafeMode(
|
||||||
@NonNull ParcelUuid subGroup, @NonNull TelephonySubscriptionSnapshot snapshot)
|
@NonNull ParcelUuid subGroup,
|
||||||
|
@NonNull TelephonySubscriptionSnapshot snapshot,
|
||||||
|
boolean isInSafeMode)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
verify(mMockDeps)
|
verify(mMockDeps)
|
||||||
.newVcn(
|
.newVcn(
|
||||||
@@ -913,22 +904,32 @@ public class VcnManagementServiceTest {
|
|||||||
mVcnCallbackCaptor.capture());
|
mVcnCallbackCaptor.capture());
|
||||||
|
|
||||||
VcnCallback vcnCallback = mVcnCallbackCaptor.getValue();
|
VcnCallback vcnCallback = mVcnCallbackCaptor.getValue();
|
||||||
vcnCallback.onEnteredSafeMode();
|
vcnCallback.onSafeModeStatusChanged(isInSafeMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
private void verifyVcnSafeModeChangesNotifiesPolicyListeners(boolean enterSafeMode)
|
||||||
public void testVcnEnteringSafeModeNotifiesPolicyListeners() throws Exception {
|
throws Exception {
|
||||||
TelephonySubscriptionSnapshot snapshot =
|
TelephonySubscriptionSnapshot snapshot =
|
||||||
triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1));
|
triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1));
|
||||||
|
|
||||||
mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
|
mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
|
||||||
|
|
||||||
triggerVcnSafeMode(TEST_UUID_1, snapshot);
|
triggerVcnSafeMode(TEST_UUID_1, snapshot, enterSafeMode);
|
||||||
|
|
||||||
verify(mMockPolicyListener).onPolicyChanged();
|
verify(mMockPolicyListener).onPolicyChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void triggerVcnStatusCallbackOnEnteredSafeMode(
|
@Test
|
||||||
|
public void testVcnEnteringSafeModeNotifiesPolicyListeners() throws Exception {
|
||||||
|
verifyVcnSafeModeChangesNotifiesPolicyListeners(true /* enterSafeMode */);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVcnExitingSafeModeNotifiesPolicyListeners() throws Exception {
|
||||||
|
verifyVcnSafeModeChangesNotifiesPolicyListeners(false /* enterSafeMode */);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void triggerVcnStatusCallbackOnSafeModeStatusChanged(
|
||||||
@NonNull ParcelUuid subGroup,
|
@NonNull ParcelUuid subGroup,
|
||||||
@NonNull String pkgName,
|
@NonNull String pkgName,
|
||||||
int uid,
|
int uid,
|
||||||
@@ -951,12 +952,13 @@ public class VcnManagementServiceTest {
|
|||||||
|
|
||||||
mVcnMgmtSvc.registerVcnStatusCallback(subGroup, mMockStatusCallback, pkgName);
|
mVcnMgmtSvc.registerVcnStatusCallback(subGroup, mMockStatusCallback, pkgName);
|
||||||
|
|
||||||
triggerVcnSafeMode(subGroup, snapshot);
|
triggerVcnSafeMode(subGroup, snapshot, true /* enterSafeMode */);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testVcnStatusCallbackOnEnteredSafeModeWithCarrierPrivileges() throws Exception {
|
public void testVcnStatusCallbackOnSafeModeStatusChangedWithCarrierPrivileges()
|
||||||
triggerVcnStatusCallbackOnEnteredSafeMode(
|
throws Exception {
|
||||||
|
triggerVcnStatusCallbackOnSafeModeStatusChanged(
|
||||||
TEST_UUID_1,
|
TEST_UUID_1,
|
||||||
TEST_PACKAGE_NAME,
|
TEST_PACKAGE_NAME,
|
||||||
TEST_UID,
|
TEST_UID,
|
||||||
@@ -967,8 +969,9 @@ public class VcnManagementServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testVcnStatusCallbackOnEnteredSafeModeWithoutCarrierPrivileges() throws Exception {
|
public void testVcnStatusCallbackOnSafeModeStatusChangedWithoutCarrierPrivileges()
|
||||||
triggerVcnStatusCallbackOnEnteredSafeMode(
|
throws Exception {
|
||||||
|
triggerVcnStatusCallbackOnSafeModeStatusChanged(
|
||||||
TEST_UUID_1,
|
TEST_UUID_1,
|
||||||
TEST_PACKAGE_NAME,
|
TEST_PACKAGE_NAME,
|
||||||
TEST_UID,
|
TEST_UID,
|
||||||
@@ -980,8 +983,9 @@ public class VcnManagementServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testVcnStatusCallbackOnEnteredSafeModeWithoutLocationPermission() throws Exception {
|
public void testVcnStatusCallbackOnSafeModeStatusChangedWithoutLocationPermission()
|
||||||
triggerVcnStatusCallbackOnEnteredSafeMode(
|
throws Exception {
|
||||||
|
triggerVcnStatusCallbackOnSafeModeStatusChanged(
|
||||||
TEST_UUID_1,
|
TEST_UUID_1,
|
||||||
TEST_PACKAGE_NAME,
|
TEST_PACKAGE_NAME,
|
||||||
TEST_UID,
|
TEST_UID,
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import static org.junit.Assert.assertFalse;
|
|||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.Matchers.any;
|
import static org.mockito.Matchers.any;
|
||||||
import static org.mockito.Matchers.anyInt;
|
import static org.mockito.Matchers.anyInt;
|
||||||
|
import static org.mockito.Matchers.argThat;
|
||||||
import static org.mockito.Matchers.eq;
|
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;
|
||||||
@@ -40,6 +41,8 @@ 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;
|
||||||
|
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
import android.net.LinkAddress;
|
||||||
import android.net.LinkProperties;
|
import android.net.LinkProperties;
|
||||||
import android.net.NetworkAgent;
|
import android.net.NetworkAgent;
|
||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
@@ -58,19 +61,29 @@ import org.junit.runner.RunWith;
|
|||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/** Tests for VcnGatewayConnection.ConnectedState */
|
/** Tests for VcnGatewayConnection.ConnectedState */
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@SmallTest
|
@SmallTest
|
||||||
public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnectionTestBase {
|
public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnectionTestBase {
|
||||||
private VcnIkeSession mIkeSession;
|
private VcnIkeSession mIkeSession;
|
||||||
|
private NetworkAgent mNetworkAgent;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
|
|
||||||
|
mNetworkAgent = mock(NetworkAgent.class);
|
||||||
|
doReturn(mNetworkAgent)
|
||||||
|
.when(mDeps)
|
||||||
|
.newNetworkAgent(any(), any(), any(), any(), anyInt(), any(), any(), any(), any());
|
||||||
|
|
||||||
mGatewayConnection.setUnderlyingNetwork(TEST_UNDERLYING_NETWORK_RECORD_1);
|
mGatewayConnection.setUnderlyingNetwork(TEST_UNDERLYING_NETWORK_RECORD_1);
|
||||||
|
|
||||||
mIkeSession = mGatewayConnection.buildIkeSession(TEST_UNDERLYING_NETWORK_RECORD_1.network);
|
mIkeSession = mGatewayConnection.buildIkeSession(TEST_UNDERLYING_NETWORK_RECORD_1.network);
|
||||||
@@ -159,21 +172,44 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
|
|||||||
assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState());
|
assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
private void triggerChildOpened() {
|
||||||
public void testChildOpenedRegistersNetwork() throws Exception {
|
triggerChildOpened(Collections.singletonList(TEST_INTERNAL_ADDR), TEST_DNS_ADDR);
|
||||||
// Verify scheduled but not canceled when entering ConnectedState
|
}
|
||||||
verifySafeModeTimeoutAlarmAndGetCallback(false /* expectCanceled */);
|
|
||||||
|
|
||||||
|
private void triggerChildOpened(List<LinkAddress> internalAddresses, InetAddress dnsAddress) {
|
||||||
final VcnChildSessionConfiguration mMockChildSessionConfig =
|
final VcnChildSessionConfiguration mMockChildSessionConfig =
|
||||||
mock(VcnChildSessionConfiguration.class);
|
mock(VcnChildSessionConfiguration.class);
|
||||||
doReturn(Collections.singletonList(TEST_INTERNAL_ADDR))
|
doReturn(internalAddresses).when(mMockChildSessionConfig).getInternalAddresses();
|
||||||
.when(mMockChildSessionConfig)
|
doReturn(Collections.singletonList(dnsAddress))
|
||||||
.getInternalAddresses();
|
|
||||||
doReturn(Collections.singletonList(TEST_DNS_ADDR))
|
|
||||||
.when(mMockChildSessionConfig)
|
.when(mMockChildSessionConfig)
|
||||||
.getInternalDnsServers();
|
.getInternalDnsServers();
|
||||||
|
|
||||||
getChildSessionCallback().onOpened(mMockChildSessionConfig);
|
getChildSessionCallback().onOpened(mMockChildSessionConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void triggerValidation(int status) {
|
||||||
|
final ArgumentCaptor<Consumer<Integer>> validationCallbackCaptor =
|
||||||
|
ArgumentCaptor.forClass(Consumer.class);
|
||||||
|
verify(mDeps)
|
||||||
|
.newNetworkAgent(
|
||||||
|
any(),
|
||||||
|
any(),
|
||||||
|
any(),
|
||||||
|
any(),
|
||||||
|
anyInt(),
|
||||||
|
any(),
|
||||||
|
any(),
|
||||||
|
any(),
|
||||||
|
validationCallbackCaptor.capture());
|
||||||
|
|
||||||
|
validationCallbackCaptor.getValue().accept(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChildOpenedRegistersNetwork() throws Exception {
|
||||||
|
// Verify scheduled but not canceled when entering ConnectedState
|
||||||
|
verifySafeModeTimeoutAlarmAndGetCallback(false /* expectCanceled */);
|
||||||
|
triggerChildOpened();
|
||||||
mTestLooper.dispatchAll();
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState());
|
assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState());
|
||||||
@@ -182,15 +218,20 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
|
|||||||
ArgumentCaptor.forClass(LinkProperties.class);
|
ArgumentCaptor.forClass(LinkProperties.class);
|
||||||
final ArgumentCaptor<NetworkCapabilities> ncCaptor =
|
final ArgumentCaptor<NetworkCapabilities> ncCaptor =
|
||||||
ArgumentCaptor.forClass(NetworkCapabilities.class);
|
ArgumentCaptor.forClass(NetworkCapabilities.class);
|
||||||
verify(mConnMgr)
|
verify(mDeps)
|
||||||
.registerNetworkAgent(
|
.newNetworkAgent(
|
||||||
any(),
|
eq(mVcnContext),
|
||||||
any(),
|
any(String.class),
|
||||||
lpCaptor.capture(),
|
|
||||||
ncCaptor.capture(),
|
ncCaptor.capture(),
|
||||||
|
lpCaptor.capture(),
|
||||||
|
anyInt(),
|
||||||
|
argThat(nac -> nac.getLegacyType() == ConnectivityManager.TYPE_MOBILE),
|
||||||
any(),
|
any(),
|
||||||
any(),
|
any(),
|
||||||
anyInt());
|
any());
|
||||||
|
verify(mNetworkAgent).register();
|
||||||
|
verify(mNetworkAgent).markConnected();
|
||||||
|
|
||||||
verify(mIpSecSvc)
|
verify(mIpSecSvc)
|
||||||
.addAddressToTunnelInterface(
|
.addAddressToTunnelInterface(
|
||||||
eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(TEST_INTERNAL_ADDR), any());
|
eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(TEST_INTERNAL_ADDR), any());
|
||||||
@@ -208,9 +249,78 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
|
|||||||
|
|
||||||
// Now that Vcn Network is up, notify it as validated and verify the SafeMode alarm is
|
// Now that Vcn Network is up, notify it as validated and verify the SafeMode alarm is
|
||||||
// canceled
|
// canceled
|
||||||
mGatewayConnection.mNetworkAgent.onValidationStatus(
|
triggerValidation(NetworkAgent.VALIDATION_STATUS_VALID);
|
||||||
NetworkAgent.VALIDATION_STATUS_VALID, null /* redirectUri */);
|
|
||||||
verify(mSafeModeTimeoutAlarm).cancel();
|
verify(mSafeModeTimeoutAlarm).cancel();
|
||||||
|
assertFalse(mGatewayConnection.isInSafeMode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInternalAndDnsAddressesChanged() throws Exception {
|
||||||
|
final List<LinkAddress> startingInternalAddrs =
|
||||||
|
Arrays.asList(new LinkAddress[] {TEST_INTERNAL_ADDR, TEST_INTERNAL_ADDR_2});
|
||||||
|
triggerChildOpened(startingInternalAddrs, TEST_DNS_ADDR);
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
for (LinkAddress addr : startingInternalAddrs) {
|
||||||
|
verify(mIpSecSvc)
|
||||||
|
.addAddressToTunnelInterface(
|
||||||
|
eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(addr), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
verify(mDeps)
|
||||||
|
.newNetworkAgent(
|
||||||
|
any(),
|
||||||
|
any(),
|
||||||
|
any(),
|
||||||
|
argThat(
|
||||||
|
lp ->
|
||||||
|
startingInternalAddrs.equals(lp.getLinkAddresses())
|
||||||
|
&& Collections.singletonList(TEST_DNS_ADDR)
|
||||||
|
.equals(lp.getDnsServers())),
|
||||||
|
anyInt(),
|
||||||
|
any(),
|
||||||
|
any(),
|
||||||
|
any(),
|
||||||
|
any());
|
||||||
|
|
||||||
|
// Trigger another connection event, and verify that the addresses change
|
||||||
|
final List<LinkAddress> newInternalAddrs =
|
||||||
|
Arrays.asList(new LinkAddress[] {TEST_INTERNAL_ADDR_2, TEST_INTERNAL_ADDR_3});
|
||||||
|
triggerChildOpened(newInternalAddrs, TEST_DNS_ADDR_2);
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
// Verify addresses on tunnel network added/removed
|
||||||
|
for (LinkAddress addr : newInternalAddrs) {
|
||||||
|
verify(mIpSecSvc)
|
||||||
|
.addAddressToTunnelInterface(
|
||||||
|
eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(addr), any());
|
||||||
|
}
|
||||||
|
verify(mIpSecSvc)
|
||||||
|
.removeAddressFromTunnelInterface(
|
||||||
|
eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(TEST_INTERNAL_ADDR), any());
|
||||||
|
|
||||||
|
// TODO(b/184579891): Also verify link properties updated and sent when sendLinkProperties
|
||||||
|
// is mockable
|
||||||
|
|
||||||
|
// Verify that IpSecTunnelInterface only created once
|
||||||
|
verify(mIpSecSvc).createTunnelInterface(any(), any(), any(), any(), any());
|
||||||
|
verifyNoMoreInteractions(mIpSecSvc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccessfulConnectionExitsSafeMode() throws Exception {
|
||||||
|
verifySafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent(
|
||||||
|
mGatewayConnection.mConnectedState);
|
||||||
|
|
||||||
|
assertTrue(mGatewayConnection.isInSafeMode());
|
||||||
|
assertFalse(mGatewayConnection.isQuitting());
|
||||||
|
|
||||||
|
triggerChildOpened();
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
triggerValidation(NetworkAgent.VALIDATION_STATUS_VALID);
|
||||||
|
|
||||||
|
assertFalse(mGatewayConnection.isInSafeMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -118,8 +118,9 @@ public class VcnGatewayConnectionConnectingStateTest extends VcnGatewayConnectio
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSafeModeTimeoutNotifiesCallback() {
|
public void testSafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent() {
|
||||||
verifySafeModeTimeoutNotifiesCallback(mGatewayConnection.mConnectingState);
|
verifySafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent(
|
||||||
|
mGatewayConnection.mConnectingState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -86,8 +86,9 @@ public class VcnGatewayConnectionDisconnectingStateTest extends VcnGatewayConnec
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSafeModeTimeoutNotifiesCallback() {
|
public void testSafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent() {
|
||||||
verifySafeModeTimeoutNotifiesCallback(mGatewayConnection.mDisconnectingState);
|
verifySafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent(
|
||||||
|
mGatewayConnection.mDisconnectingState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -96,8 +96,9 @@ public class VcnGatewayConnectionRetryTimeoutStateTest extends VcnGatewayConnect
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSafeModeTimeoutNotifiesCallback() {
|
public void testSafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent() {
|
||||||
verifySafeModeTimeoutNotifiesCallback(mGatewayConnection.mRetryTimeoutState);
|
verifySafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent(
|
||||||
|
mGatewayConnection.mRetryTimeoutState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession;
|
|||||||
import static com.android.server.vcn.VcnTestUtils.setupIpSecManager;
|
import static com.android.server.vcn.VcnTestUtils.setupIpSecManager;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.Matchers.any;
|
import static org.mockito.Matchers.any;
|
||||||
import static org.mockito.Matchers.eq;
|
import static org.mockito.Matchers.eq;
|
||||||
import static org.mockito.Mockito.atLeastOnce;
|
import static org.mockito.Mockito.atLeastOnce;
|
||||||
@@ -42,6 +44,7 @@ import android.net.IpSecTunnelInterfaceResponse;
|
|||||||
import android.net.LinkAddress;
|
import android.net.LinkAddress;
|
||||||
import android.net.LinkProperties;
|
import android.net.LinkProperties;
|
||||||
import android.net.Network;
|
import android.net.Network;
|
||||||
|
import android.net.NetworkAgent;
|
||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
import android.net.ipsec.ike.ChildSessionCallback;
|
import android.net.ipsec.ike.ChildSessionCallback;
|
||||||
import android.net.ipsec.ike.IkeSessionCallback;
|
import android.net.ipsec.ike.IkeSessionCallback;
|
||||||
@@ -71,8 +74,14 @@ public class VcnGatewayConnectionTestBase {
|
|||||||
protected static final ParcelUuid TEST_SUB_GRP = new ParcelUuid(UUID.randomUUID());
|
protected static final ParcelUuid TEST_SUB_GRP = new ParcelUuid(UUID.randomUUID());
|
||||||
protected static final InetAddress TEST_DNS_ADDR =
|
protected static final InetAddress TEST_DNS_ADDR =
|
||||||
InetAddresses.parseNumericAddress("2001:DB8:0:1::");
|
InetAddresses.parseNumericAddress("2001:DB8:0:1::");
|
||||||
|
protected static final InetAddress TEST_DNS_ADDR_2 =
|
||||||
|
InetAddresses.parseNumericAddress("2001:DB8:0:2::");
|
||||||
protected static final LinkAddress TEST_INTERNAL_ADDR =
|
protected static final LinkAddress TEST_INTERNAL_ADDR =
|
||||||
new LinkAddress(InetAddresses.parseNumericAddress("2001:DB8:0:2::"), 64);
|
new LinkAddress(InetAddresses.parseNumericAddress("2001:DB8:1:1::"), 64);
|
||||||
|
protected static final LinkAddress TEST_INTERNAL_ADDR_2 =
|
||||||
|
new LinkAddress(InetAddresses.parseNumericAddress("2001:DB8:1:2::"), 64);
|
||||||
|
protected static final LinkAddress TEST_INTERNAL_ADDR_3 =
|
||||||
|
new LinkAddress(InetAddresses.parseNumericAddress("2001:DB8:1:3::"), 64);
|
||||||
|
|
||||||
protected static final int TEST_IPSEC_SPI_VALUE = 0x1234;
|
protected static final int TEST_IPSEC_SPI_VALUE = 0x1234;
|
||||||
protected static final int TEST_IPSEC_SPI_RESOURCE_ID = 1;
|
protected static final int TEST_IPSEC_SPI_RESOURCE_ID = 1;
|
||||||
@@ -267,7 +276,12 @@ public class VcnGatewayConnectionTestBase {
|
|||||||
expectCanceled);
|
expectCanceled);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void verifySafeModeTimeoutNotifiesCallback(@NonNull State expectedState) {
|
protected void verifySafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent(
|
||||||
|
@NonNull State expectedState) {
|
||||||
|
// Set a NetworkAgent, and expect it to be unregistered and cleared
|
||||||
|
final NetworkAgent mockNetworkAgent = mock(NetworkAgent.class);
|
||||||
|
mGatewayConnection.setNetworkAgent(mockNetworkAgent);
|
||||||
|
|
||||||
// SafeMode timer starts when VcnGatewayConnection exits DisconnectedState (the initial
|
// SafeMode timer starts when VcnGatewayConnection exits DisconnectedState (the initial
|
||||||
// state)
|
// state)
|
||||||
final Runnable delayedEvent =
|
final Runnable delayedEvent =
|
||||||
@@ -275,7 +289,11 @@ public class VcnGatewayConnectionTestBase {
|
|||||||
delayedEvent.run();
|
delayedEvent.run();
|
||||||
mTestLooper.dispatchAll();
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
verify(mGatewayStatusCallback).onEnteredSafeMode();
|
verify(mGatewayStatusCallback).onSafeModeStatusChanged();
|
||||||
assertEquals(expectedState, mGatewayConnection.getCurrentState());
|
assertEquals(expectedState, mGatewayConnection.getCurrentState());
|
||||||
|
assertTrue(mGatewayConnection.isInSafeMode());
|
||||||
|
|
||||||
|
verify(mockNetworkAgent).unregister();
|
||||||
|
assertNull(mGatewayConnection.getNetworkAgent());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,14 +19,13 @@ package com.android.server.vcn;
|
|||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
|
||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
|
||||||
|
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
||||||
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
|
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
|
||||||
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_INACTIVE;
|
|
||||||
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
|
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
|
||||||
|
|
||||||
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;
|
||||||
import static org.mockito.Matchers.argThat;
|
|
||||||
import static org.mockito.Matchers.eq;
|
import static org.mockito.Matchers.eq;
|
||||||
import static org.mockito.Mockito.doAnswer;
|
import static org.mockito.Mockito.doAnswer;
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
@@ -54,7 +53,6 @@ import org.junit.Test;
|
|||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -136,6 +134,7 @@ public class VcnTest {
|
|||||||
private void startVcnGatewayWithCapabilities(
|
private void startVcnGatewayWithCapabilities(
|
||||||
NetworkRequestListener requestListener, int... netCapabilities) {
|
NetworkRequestListener requestListener, int... netCapabilities) {
|
||||||
final NetworkRequest.Builder requestBuilder = new NetworkRequest.Builder();
|
final NetworkRequest.Builder requestBuilder = new NetworkRequest.Builder();
|
||||||
|
requestBuilder.addTransportType(TRANSPORT_CELLULAR);
|
||||||
for (final int netCapability : netCapabilities) {
|
for (final int netCapability : netCapabilities) {
|
||||||
requestBuilder.addCapability(netCapability);
|
requestBuilder.addCapability(netCapability);
|
||||||
}
|
}
|
||||||
@@ -160,8 +159,7 @@ public class VcnTest {
|
|||||||
mTestLooper.dispatchAll();
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
for (final VcnGatewayConnection gateway : gatewayConnections) {
|
for (final VcnGatewayConnection gateway : gatewayConnections) {
|
||||||
verify(gateway, status == VCN_STATUS_CODE_ACTIVE ? times(1) : never())
|
verify(gateway).updateSubscriptionSnapshot(eq(updatedSnapshot));
|
||||||
.updateSubscriptionSnapshot(eq(updatedSnapshot));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,32 +200,53 @@ public class VcnTest {
|
|||||||
|
|
||||||
private void verifySafeMode(
|
private void verifySafeMode(
|
||||||
NetworkRequestListener requestListener,
|
NetworkRequestListener requestListener,
|
||||||
Set<VcnGatewayConnection> expectedGatewaysTornDown) {
|
Set<VcnGatewayConnection> activeGateways,
|
||||||
assertEquals(VCN_STATUS_CODE_SAFE_MODE, mVcn.getStatus());
|
boolean expectInSafeMode) {
|
||||||
for (final VcnGatewayConnection gatewayConnection : expectedGatewaysTornDown) {
|
for (VcnGatewayConnection gatewayConnection : activeGateways) {
|
||||||
verify(gatewayConnection).teardownAsynchronously();
|
verify(gatewayConnection, never()).teardownAsynchronously();
|
||||||
}
|
}
|
||||||
verify(mVcnNetworkProvider).unregisterListener(requestListener);
|
|
||||||
verify(mVcnCallback).onEnteredSafeMode();
|
assertEquals(
|
||||||
|
expectInSafeMode ? VCN_STATUS_CODE_SAFE_MODE : VCN_STATUS_CODE_ACTIVE,
|
||||||
|
mVcn.getStatus());
|
||||||
|
verify(mVcnCallback).onSafeModeStatusChanged(expectInSafeMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGatewayEnteringSafeModeNotifiesVcn() {
|
public void testGatewayEnteringAndExitingSafeModeNotifiesVcn() {
|
||||||
final NetworkRequestListener requestListener = verifyAndGetRequestListener();
|
final NetworkRequestListener requestListener = verifyAndGetRequestListener();
|
||||||
final Set<VcnGatewayConnection> gatewayConnections =
|
final Set<VcnGatewayConnection> gatewayConnections =
|
||||||
startGatewaysAndGetGatewayConnections(requestListener);
|
startGatewaysAndGetGatewayConnections(requestListener);
|
||||||
|
|
||||||
// Doesn't matter which callback this gets - any Gateway entering Safemode should shut down
|
// Doesn't matter which callback this gets, or which VCN is in safe mode - any Gateway
|
||||||
// all Gateways
|
// entering Safemode should trigger safe mode
|
||||||
final VcnGatewayStatusCallback statusCallback = mGatewayStatusCallbackCaptor.getValue();
|
final VcnGatewayStatusCallback statusCallback = mGatewayStatusCallbackCaptor.getValue();
|
||||||
statusCallback.onEnteredSafeMode();
|
final VcnGatewayConnection gatewayConnection = gatewayConnections.iterator().next();
|
||||||
|
|
||||||
|
doReturn(true).when(gatewayConnection).isInSafeMode();
|
||||||
|
statusCallback.onSafeModeStatusChanged();
|
||||||
mTestLooper.dispatchAll();
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
verifySafeMode(requestListener, gatewayConnections);
|
verifySafeMode(requestListener, gatewayConnections, true /* expectInSafeMode */);
|
||||||
|
|
||||||
|
// Verify that when all GatewayConnections exit safe mode, the VCN also exits safe mode
|
||||||
|
doReturn(false).when(gatewayConnection).isInSafeMode();
|
||||||
|
statusCallback.onSafeModeStatusChanged();
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
verifySafeMode(requestListener, gatewayConnections, false /* expectInSafeMode */);
|
||||||
|
|
||||||
|
// Re-trigger, verify safe mode callback does not get fired again for identical state
|
||||||
|
statusCallback.onSafeModeStatusChanged();
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
// Expect only once still; from above.
|
||||||
|
verify(mVcnCallback).onSafeModeStatusChanged(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
private void verifyGatewayQuit(int status) {
|
||||||
public void testGatewayQuit() {
|
mVcn.setStatus(status);
|
||||||
|
|
||||||
final NetworkRequestListener requestListener = verifyAndGetRequestListener();
|
final NetworkRequestListener requestListener = verifyAndGetRequestListener();
|
||||||
final Set<VcnGatewayConnection> gatewayConnections =
|
final Set<VcnGatewayConnection> gatewayConnections =
|
||||||
new ArraySet<>(startGatewaysAndGetGatewayConnections(requestListener));
|
new ArraySet<>(startGatewaysAndGetGatewayConnections(requestListener));
|
||||||
@@ -240,7 +259,7 @@ public class VcnTest {
|
|||||||
assertEquals(1, mVcn.getVcnGatewayConnections().size());
|
assertEquals(1, mVcn.getVcnGatewayConnections().size());
|
||||||
verify(mVcnNetworkProvider).resendAllRequests(requestListener);
|
verify(mVcnNetworkProvider).resendAllRequests(requestListener);
|
||||||
|
|
||||||
// Verify that the VcnGatewayConnection is restarted
|
// Verify that the VcnGatewayConnection is restarted if a request exists for it
|
||||||
triggerVcnRequestListeners(requestListener);
|
triggerVcnRequestListeners(requestListener);
|
||||||
mTestLooper.dispatchAll();
|
mTestLooper.dispatchAll();
|
||||||
assertEquals(2, mVcn.getVcnGatewayConnections().size());
|
assertEquals(2, mVcn.getVcnGatewayConnections().size());
|
||||||
@@ -254,21 +273,13 @@ public class VcnTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGatewayQuitWhileInactive() {
|
public void testGatewayQuitReevaluatesRequests() {
|
||||||
final NetworkRequestListener requestListener = verifyAndGetRequestListener();
|
verifyGatewayQuit(VCN_STATUS_CODE_ACTIVE);
|
||||||
final Set<VcnGatewayConnection> gatewayConnections =
|
}
|
||||||
new ArraySet<>(startGatewaysAndGetGatewayConnections(requestListener));
|
|
||||||
|
|
||||||
mVcn.teardownAsynchronously();
|
@Test
|
||||||
mTestLooper.dispatchAll();
|
public void testGatewayQuitReevaluatesRequestsInSafeMode() {
|
||||||
|
verifyGatewayQuit(VCN_STATUS_CODE_SAFE_MODE);
|
||||||
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, never()).resendAllRequests(requestListener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -298,49 +309,4 @@ public class VcnTest {
|
|||||||
verify(removedGatewayConnection).teardownAsynchronously();
|
verify(removedGatewayConnection).teardownAsynchronously();
|
||||||
verify(mVcnNetworkProvider).resendAllRequests(requestListener);
|
verify(mVcnNetworkProvider).resendAllRequests(requestListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUpdateConfigExitsSafeMode() {
|
|
||||||
final NetworkRequestListener requestListener = verifyAndGetRequestListener();
|
|
||||||
final Set<VcnGatewayConnection> gatewayConnections =
|
|
||||||
new ArraySet<>(startGatewaysAndGetGatewayConnections(requestListener));
|
|
||||||
|
|
||||||
final VcnGatewayStatusCallback statusCallback = mGatewayStatusCallbackCaptor.getValue();
|
|
||||||
statusCallback.onEnteredSafeMode();
|
|
||||||
mTestLooper.dispatchAll();
|
|
||||||
verifySafeMode(requestListener, gatewayConnections);
|
|
||||||
|
|
||||||
doAnswer(invocation -> {
|
|
||||||
final NetworkRequestListener listener = invocation.getArgument(0);
|
|
||||||
triggerVcnRequestListeners(listener);
|
|
||||||
return null;
|
|
||||||
}).when(mVcnNetworkProvider).registerListener(eq(requestListener));
|
|
||||||
|
|
||||||
mVcn.updateConfig(mConfig);
|
|
||||||
mTestLooper.dispatchAll();
|
|
||||||
|
|
||||||
// Registered on start, then re-registered with new configs
|
|
||||||
verify(mVcnNetworkProvider, times(2)).registerListener(eq(requestListener));
|
|
||||||
assertEquals(VCN_STATUS_CODE_ACTIVE, mVcn.getStatus());
|
|
||||||
for (final int[] caps : TEST_CAPS) {
|
|
||||||
// Expect each gateway connection created only on initial startup
|
|
||||||
verify(mDeps)
|
|
||||||
.newVcnGatewayConnection(
|
|
||||||
eq(mVcnContext),
|
|
||||||
eq(TEST_SUB_GROUP),
|
|
||||||
eq(mSubscriptionSnapshot),
|
|
||||||
argThat(config -> Arrays.equals(caps, config.getExposedCapabilities())),
|
|
||||||
any());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIgnoreNetworkRequestWhileInactive() {
|
|
||||||
mVcn.setStatus(VCN_STATUS_CODE_INACTIVE);
|
|
||||||
|
|
||||||
final NetworkRequestListener requestListener = verifyAndGetRequestListener();
|
|
||||||
triggerVcnRequestListeners(requestListener);
|
|
||||||
|
|
||||||
verify(mDeps, never()).newVcnGatewayConnection(any(), any(), any(), any(), any());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user