Merge changes I128a894c,I3336c150
* changes: Remove use of locks in VcnGatewayConnection. Support Safemode for VCNs.
This commit is contained in:
@@ -66,6 +66,7 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -291,8 +292,9 @@ public class VcnManagementService extends IVcnManagementService.Stub {
|
|||||||
@NonNull VcnContext vcnContext,
|
@NonNull VcnContext vcnContext,
|
||||||
@NonNull ParcelUuid subscriptionGroup,
|
@NonNull ParcelUuid subscriptionGroup,
|
||||||
@NonNull VcnConfig config,
|
@NonNull VcnConfig config,
|
||||||
@NonNull TelephonySubscriptionSnapshot snapshot) {
|
@NonNull TelephonySubscriptionSnapshot snapshot,
|
||||||
return new Vcn(vcnContext, subscriptionGroup, config, snapshot);
|
@NonNull VcnSafemodeCallback safemodeCallback) {
|
||||||
|
return new Vcn(vcnContext, subscriptionGroup, config, snapshot, safemodeCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the subId indicated by the given {@link WifiInfo}. */
|
/** Gets the subId indicated by the given {@link WifiInfo}. */
|
||||||
@@ -438,7 +440,12 @@ public class VcnManagementService extends IVcnManagementService.Stub {
|
|||||||
// TODO(b/176939047): Support multiple VCNs active at the same time, or limit to one active
|
// TODO(b/176939047): Support multiple VCNs active at the same time, or limit to one active
|
||||||
// VCN.
|
// VCN.
|
||||||
|
|
||||||
final Vcn newInstance = mDeps.newVcn(mVcnContext, subscriptionGroup, config, mLastSnapshot);
|
final VcnSafemodeCallbackImpl safemodeCallback =
|
||||||
|
new VcnSafemodeCallbackImpl(subscriptionGroup);
|
||||||
|
|
||||||
|
final Vcn newInstance =
|
||||||
|
mDeps.newVcn(
|
||||||
|
mVcnContext, subscriptionGroup, config, mLastSnapshot, safemodeCallback);
|
||||||
mVcns.put(subscriptionGroup, newInstance);
|
mVcns.put(subscriptionGroup, newInstance);
|
||||||
|
|
||||||
// Now that a new VCN has started, notify all registered listeners to refresh their
|
// Now that a new VCN has started, notify all registered listeners to refresh their
|
||||||
@@ -536,7 +543,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get current configuration list for testing purposes */
|
/** Get current VCNs for testing purposes */
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
public Map<ParcelUuid, Vcn> getAllVcns() {
|
public Map<ParcelUuid, Vcn> getAllVcns() {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
@@ -638,8 +645,8 @@ public class VcnManagementService extends IVcnManagementService.Stub {
|
|||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
ParcelUuid subGroup = mLastSnapshot.getGroupForSubId(subId);
|
ParcelUuid subGroup = mLastSnapshot.getGroupForSubId(subId);
|
||||||
|
|
||||||
// TODO(b/178140910): only mark the Network as VCN-managed if not in safe mode
|
Vcn vcn = mVcns.get(subGroup);
|
||||||
if (mVcns.containsKey(subGroup)) {
|
if (vcn != null && vcn.isActive()) {
|
||||||
isVcnManagedNetwork = true;
|
isVcnManagedNetwork = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -651,4 +658,31 @@ public class VcnManagementService extends IVcnManagementService.Stub {
|
|||||||
|
|
||||||
return new VcnUnderlyingNetworkPolicy(false /* isTearDownRequested */, networkCapabilities);
|
return new VcnUnderlyingNetworkPolicy(false /* isTearDownRequested */, networkCapabilities);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Callback for signalling when a Vcn has entered Safemode. */
|
||||||
|
public interface VcnSafemodeCallback {
|
||||||
|
/** Called by a Vcn to signal that it has entered Safemode. */
|
||||||
|
void onEnteredSafemode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** VcnSafemodeCallback is used by Vcns to notify VcnManagementService on entering Safemode. */
|
||||||
|
private class VcnSafemodeCallbackImpl implements VcnSafemodeCallback {
|
||||||
|
@NonNull private final ParcelUuid mSubGroup;
|
||||||
|
|
||||||
|
private VcnSafemodeCallbackImpl(@NonNull final ParcelUuid subGroup) {
|
||||||
|
mSubGroup = Objects.requireNonNull(subGroup, "Missing subGroup");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnteredSafemode() {
|
||||||
|
synchronized (mLock) {
|
||||||
|
// Ignore if this subscription group doesn't exist anymore
|
||||||
|
if (!mVcns.containsKey(mSubGroup)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyAllPolicyListenersLocked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import android.util.Slog;
|
|||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.annotations.VisibleForTesting.Visibility;
|
import com.android.internal.annotations.VisibleForTesting.Visibility;
|
||||||
|
import com.android.server.VcnManagementService.VcnSafemodeCallback;
|
||||||
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -37,6 +38,7 @@ import java.util.HashSet;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an single instance of a VCN.
|
* Represents an single instance of a VCN.
|
||||||
@@ -82,10 +84,19 @@ public class Vcn extends Handler {
|
|||||||
/** 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 Safemode.
|
||||||
|
*
|
||||||
|
* <p>Upon entering Safemode, the VCN will unregister its RequestListener, tear down all of its
|
||||||
|
* VcnGatewayConnections, and notify VcnManagementService that it is in Safemode.
|
||||||
|
*/
|
||||||
|
private static final int MSG_CMD_ENTER_SAFEMODE = 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;
|
||||||
@NonNull private final VcnNetworkRequestListener mRequestListener;
|
@NonNull private final VcnNetworkRequestListener mRequestListener;
|
||||||
|
@NonNull private final VcnSafemodeCallback mVcnSafemodeCallback;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private final Map<VcnGatewayConnectionConfig, VcnGatewayConnection> mVcnGatewayConnections =
|
private final Map<VcnGatewayConnectionConfig, VcnGatewayConnection> mVcnGatewayConnections =
|
||||||
@@ -94,14 +105,33 @@ public class Vcn extends Handler {
|
|||||||
@NonNull private VcnConfig mConfig;
|
@NonNull private VcnConfig mConfig;
|
||||||
@NonNull private TelephonySubscriptionSnapshot mLastSnapshot;
|
@NonNull private TelephonySubscriptionSnapshot mLastSnapshot;
|
||||||
|
|
||||||
private boolean mIsRunning = true;
|
/**
|
||||||
|
* Whether this Vcn instance is active and running.
|
||||||
|
*
|
||||||
|
* <p>The value will be {@code true} while running. It will be {@code false} if the VCN has been
|
||||||
|
* shut down or has entered safe mode.
|
||||||
|
*
|
||||||
|
* <p>This AtomicBoolean is required in order to ensure consistency and correctness across
|
||||||
|
* multiple threads. Unlike the rest of the Vcn, this is queried synchronously on Binder threads
|
||||||
|
* from VcnManagementService, and therefore cannot rely on guarantees of running on the VCN
|
||||||
|
* Looper.
|
||||||
|
*/
|
||||||
|
// TODO(b/179429339): update when exiting safemode (when a new VcnConfig is provided)
|
||||||
|
private final AtomicBoolean mIsActive = new AtomicBoolean(true);
|
||||||
|
|
||||||
public Vcn(
|
public Vcn(
|
||||||
@NonNull VcnContext vcnContext,
|
@NonNull VcnContext vcnContext,
|
||||||
@NonNull ParcelUuid subscriptionGroup,
|
@NonNull ParcelUuid subscriptionGroup,
|
||||||
@NonNull VcnConfig config,
|
@NonNull VcnConfig config,
|
||||||
@NonNull TelephonySubscriptionSnapshot snapshot) {
|
@NonNull TelephonySubscriptionSnapshot snapshot,
|
||||||
this(vcnContext, subscriptionGroup, config, snapshot, new Dependencies());
|
@NonNull VcnSafemodeCallback vcnSafemodeCallback) {
|
||||||
|
this(
|
||||||
|
vcnContext,
|
||||||
|
subscriptionGroup,
|
||||||
|
config,
|
||||||
|
snapshot,
|
||||||
|
vcnSafemodeCallback,
|
||||||
|
new Dependencies());
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
@@ -110,10 +140,13 @@ public class Vcn extends Handler {
|
|||||||
@NonNull ParcelUuid subscriptionGroup,
|
@NonNull ParcelUuid subscriptionGroup,
|
||||||
@NonNull VcnConfig config,
|
@NonNull VcnConfig config,
|
||||||
@NonNull TelephonySubscriptionSnapshot snapshot,
|
@NonNull TelephonySubscriptionSnapshot snapshot,
|
||||||
|
@NonNull VcnSafemodeCallback vcnSafemodeCallback,
|
||||||
@NonNull Dependencies deps) {
|
@NonNull Dependencies deps) {
|
||||||
super(Objects.requireNonNull(vcnContext, "Missing vcnContext").getLooper());
|
super(Objects.requireNonNull(vcnContext, "Missing vcnContext").getLooper());
|
||||||
mVcnContext = vcnContext;
|
mVcnContext = vcnContext;
|
||||||
mSubscriptionGroup = Objects.requireNonNull(subscriptionGroup, "Missing subscriptionGroup");
|
mSubscriptionGroup = Objects.requireNonNull(subscriptionGroup, "Missing subscriptionGroup");
|
||||||
|
mVcnSafemodeCallback =
|
||||||
|
Objects.requireNonNull(vcnSafemodeCallback, "Missing vcnSafemodeCallback");
|
||||||
mDeps = Objects.requireNonNull(deps, "Missing deps");
|
mDeps = Objects.requireNonNull(deps, "Missing deps");
|
||||||
mRequestListener = new VcnNetworkRequestListener();
|
mRequestListener = new VcnNetworkRequestListener();
|
||||||
|
|
||||||
@@ -143,6 +176,11 @@ public class Vcn extends Handler {
|
|||||||
sendMessageAtFrontOfQueue(obtainMessage(MSG_CMD_TEARDOWN));
|
sendMessageAtFrontOfQueue(obtainMessage(MSG_CMD_TEARDOWN));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Synchronously checks whether this Vcn is active. */
|
||||||
|
public boolean isActive() {
|
||||||
|
return mIsActive.get();
|
||||||
|
}
|
||||||
|
|
||||||
/** Get current Gateways for testing purposes */
|
/** Get current Gateways for testing purposes */
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
public Set<VcnGatewayConnection> getVcnGatewayConnections() {
|
public Set<VcnGatewayConnection> getVcnGatewayConnections() {
|
||||||
@@ -160,7 +198,7 @@ public class Vcn extends Handler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(@NonNull Message msg) {
|
public void handleMessage(@NonNull Message msg) {
|
||||||
if (!mIsRunning) {
|
if (!isActive()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,6 +215,9 @@ public class Vcn extends Handler {
|
|||||||
case MSG_CMD_TEARDOWN:
|
case MSG_CMD_TEARDOWN:
|
||||||
handleTeardown();
|
handleTeardown();
|
||||||
break;
|
break;
|
||||||
|
case MSG_CMD_ENTER_SAFEMODE:
|
||||||
|
handleEnterSafemode();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Slog.wtf(getLogTag(), "Unknown msg.what: " + msg.what);
|
Slog.wtf(getLogTag(), "Unknown msg.what: " + msg.what);
|
||||||
}
|
}
|
||||||
@@ -198,7 +239,13 @@ public class Vcn extends Handler {
|
|||||||
gatewayConnection.teardownAsynchronously();
|
gatewayConnection.teardownAsynchronously();
|
||||||
}
|
}
|
||||||
|
|
||||||
mIsRunning = false;
|
mIsActive.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleEnterSafemode() {
|
||||||
|
handleTeardown();
|
||||||
|
|
||||||
|
mVcnSafemodeCallback.onEnteredSafemode();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleNetworkRequested(
|
private void handleNetworkRequested(
|
||||||
@@ -233,7 +280,8 @@ public class Vcn extends Handler {
|
|||||||
mVcnContext,
|
mVcnContext,
|
||||||
mSubscriptionGroup,
|
mSubscriptionGroup,
|
||||||
mLastSnapshot,
|
mLastSnapshot,
|
||||||
gatewayConnectionConfig);
|
gatewayConnectionConfig,
|
||||||
|
new VcnGatewayStatusCallbackImpl());
|
||||||
mVcnGatewayConnections.put(gatewayConnectionConfig, vcnGatewayConnection);
|
mVcnGatewayConnections.put(gatewayConnectionConfig, vcnGatewayConnection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -242,7 +290,7 @@ public class Vcn extends Handler {
|
|||||||
private void handleSubscriptionsChanged(@NonNull TelephonySubscriptionSnapshot snapshot) {
|
private void handleSubscriptionsChanged(@NonNull TelephonySubscriptionSnapshot snapshot) {
|
||||||
mLastSnapshot = snapshot;
|
mLastSnapshot = snapshot;
|
||||||
|
|
||||||
if (mIsRunning) {
|
if (isActive()) {
|
||||||
for (VcnGatewayConnection gatewayConnection : mVcnGatewayConnections.values()) {
|
for (VcnGatewayConnection gatewayConnection : mVcnGatewayConnections.values()) {
|
||||||
gatewayConnection.updateSubscriptionSnapshot(mLastSnapshot);
|
gatewayConnection.updateSubscriptionSnapshot(mLastSnapshot);
|
||||||
}
|
}
|
||||||
@@ -271,6 +319,20 @@ public class Vcn extends Handler {
|
|||||||
return 52;
|
return 52;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Callback used for passing status signals from a VcnGatewayConnection to its managing Vcn. */
|
||||||
|
@VisibleForTesting(visibility = Visibility.PACKAGE)
|
||||||
|
public interface VcnGatewayStatusCallback {
|
||||||
|
/** Called by a VcnGatewayConnection to indicate that it has entered Safemode. */
|
||||||
|
void onEnteredSafemode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class VcnGatewayStatusCallbackImpl implements VcnGatewayStatusCallback {
|
||||||
|
@Override
|
||||||
|
public void onEnteredSafemode() {
|
||||||
|
sendMessage(obtainMessage(MSG_CMD_ENTER_SAFEMODE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** External dependencies used by Vcn, for injection in tests */
|
/** External dependencies used by Vcn, for injection in tests */
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
public static class Dependencies {
|
public static class Dependencies {
|
||||||
@@ -279,9 +341,14 @@ public class Vcn extends Handler {
|
|||||||
VcnContext vcnContext,
|
VcnContext vcnContext,
|
||||||
ParcelUuid subscriptionGroup,
|
ParcelUuid subscriptionGroup,
|
||||||
TelephonySubscriptionSnapshot snapshot,
|
TelephonySubscriptionSnapshot snapshot,
|
||||||
VcnGatewayConnectionConfig connectionConfig) {
|
VcnGatewayConnectionConfig connectionConfig,
|
||||||
|
VcnGatewayStatusCallback gatewayStatusCallback) {
|
||||||
return new VcnGatewayConnection(
|
return new VcnGatewayConnection(
|
||||||
vcnContext, subscriptionGroup, snapshot, connectionConfig);
|
vcnContext,
|
||||||
|
subscriptionGroup,
|
||||||
|
snapshot,
|
||||||
|
connectionConfig,
|
||||||
|
gatewayStatusCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ import android.os.ParcelUuid;
|
|||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
import com.android.internal.annotations.GuardedBy;
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.annotations.VisibleForTesting.Visibility;
|
import com.android.internal.annotations.VisibleForTesting.Visibility;
|
||||||
import com.android.internal.util.State;
|
import com.android.internal.util.State;
|
||||||
@@ -69,6 +68,7 @@ import com.android.internal.util.StateMachine;
|
|||||||
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
||||||
import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord;
|
import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord;
|
||||||
import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkTrackerCallback;
|
import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkTrackerCallback;
|
||||||
|
import com.android.server.vcn.Vcn.VcnGatewayStatusCallback;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.Inet4Address;
|
import java.net.Inet4Address;
|
||||||
@@ -403,15 +403,13 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
@NonNull
|
@NonNull
|
||||||
final RetryTimeoutState mRetryTimeoutState = new RetryTimeoutState();
|
final RetryTimeoutState mRetryTimeoutState = new RetryTimeoutState();
|
||||||
|
|
||||||
@NonNull private final Object mLock = new Object();
|
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
|
||||||
@NonNull private TelephonySubscriptionSnapshot mLastSnapshot;
|
@NonNull private TelephonySubscriptionSnapshot mLastSnapshot;
|
||||||
|
|
||||||
@NonNull private final VcnContext mVcnContext;
|
@NonNull private final VcnContext mVcnContext;
|
||||||
@NonNull private final ParcelUuid mSubscriptionGroup;
|
@NonNull private final ParcelUuid mSubscriptionGroup;
|
||||||
@NonNull private final UnderlyingNetworkTracker mUnderlyingNetworkTracker;
|
@NonNull private final UnderlyingNetworkTracker mUnderlyingNetworkTracker;
|
||||||
@NonNull private final VcnGatewayConnectionConfig mConnectionConfig;
|
@NonNull private final VcnGatewayConnectionConfig mConnectionConfig;
|
||||||
|
@NonNull private final VcnGatewayStatusCallback mGatewayStatusCallback;
|
||||||
@NonNull private final Dependencies mDeps;
|
@NonNull private final Dependencies mDeps;
|
||||||
|
|
||||||
@NonNull private final VcnUnderlyingNetworkTrackerCallback mUnderlyingNetworkTrackerCallback;
|
@NonNull private final VcnUnderlyingNetworkTrackerCallback mUnderlyingNetworkTrackerCallback;
|
||||||
@@ -487,8 +485,15 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
@NonNull VcnContext vcnContext,
|
@NonNull VcnContext vcnContext,
|
||||||
@NonNull ParcelUuid subscriptionGroup,
|
@NonNull ParcelUuid subscriptionGroup,
|
||||||
@NonNull TelephonySubscriptionSnapshot snapshot,
|
@NonNull TelephonySubscriptionSnapshot snapshot,
|
||||||
@NonNull VcnGatewayConnectionConfig connectionConfig) {
|
@NonNull VcnGatewayConnectionConfig connectionConfig,
|
||||||
this(vcnContext, subscriptionGroup, snapshot, connectionConfig, new Dependencies());
|
@NonNull VcnGatewayStatusCallback gatewayStatusCallback) {
|
||||||
|
this(
|
||||||
|
vcnContext,
|
||||||
|
subscriptionGroup,
|
||||||
|
snapshot,
|
||||||
|
connectionConfig,
|
||||||
|
gatewayStatusCallback,
|
||||||
|
new Dependencies());
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
@@ -497,16 +502,17 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
@NonNull ParcelUuid subscriptionGroup,
|
@NonNull ParcelUuid subscriptionGroup,
|
||||||
@NonNull TelephonySubscriptionSnapshot snapshot,
|
@NonNull TelephonySubscriptionSnapshot snapshot,
|
||||||
@NonNull VcnGatewayConnectionConfig connectionConfig,
|
@NonNull VcnGatewayConnectionConfig connectionConfig,
|
||||||
|
@NonNull VcnGatewayStatusCallback gatewayStatusCallback,
|
||||||
@NonNull Dependencies deps) {
|
@NonNull Dependencies deps) {
|
||||||
super(TAG, Objects.requireNonNull(vcnContext, "Missing vcnContext").getLooper());
|
super(TAG, Objects.requireNonNull(vcnContext, "Missing vcnContext").getLooper());
|
||||||
mVcnContext = vcnContext;
|
mVcnContext = vcnContext;
|
||||||
mSubscriptionGroup = Objects.requireNonNull(subscriptionGroup, "Missing subscriptionGroup");
|
mSubscriptionGroup = Objects.requireNonNull(subscriptionGroup, "Missing subscriptionGroup");
|
||||||
mConnectionConfig = Objects.requireNonNull(connectionConfig, "Missing connectionConfig");
|
mConnectionConfig = Objects.requireNonNull(connectionConfig, "Missing connectionConfig");
|
||||||
|
mGatewayStatusCallback =
|
||||||
|
Objects.requireNonNull(gatewayStatusCallback, "Missing gatewayStatusCallback");
|
||||||
mDeps = Objects.requireNonNull(deps, "Missing deps");
|
mDeps = Objects.requireNonNull(deps, "Missing deps");
|
||||||
|
|
||||||
synchronized (mLock) {
|
mLastSnapshot = Objects.requireNonNull(snapshot, "Missing snapshot");
|
||||||
mLastSnapshot = Objects.requireNonNull(snapshot, "Missing snapshot");
|
|
||||||
}
|
|
||||||
|
|
||||||
mUnderlyingNetworkTrackerCallback = new VcnUnderlyingNetworkTrackerCallback();
|
mUnderlyingNetworkTrackerCallback = new VcnUnderlyingNetworkTrackerCallback();
|
||||||
|
|
||||||
@@ -577,13 +583,10 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
*/
|
*/
|
||||||
public void updateSubscriptionSnapshot(@NonNull TelephonySubscriptionSnapshot snapshot) {
|
public void updateSubscriptionSnapshot(@NonNull TelephonySubscriptionSnapshot snapshot) {
|
||||||
Objects.requireNonNull(snapshot, "Missing snapshot");
|
Objects.requireNonNull(snapshot, "Missing snapshot");
|
||||||
|
mVcnContext.ensureRunningOnLooperThread();
|
||||||
|
|
||||||
// Vcn is the only user of this method and runs on the same Thread, but lock around
|
mLastSnapshot = snapshot;
|
||||||
// mLastSnapshot to be technically correct.
|
mUnderlyingNetworkTracker.updateSubscriptionSnapshot(mLastSnapshot);
|
||||||
synchronized (mLock) {
|
|
||||||
mLastSnapshot = snapshot;
|
|
||||||
mUnderlyingNetworkTracker.updateSubscriptionSnapshot(mLastSnapshot);
|
|
||||||
}
|
|
||||||
|
|
||||||
sendMessage(EVENT_SUBSCRIPTIONS_CHANGED, TOKEN_ALL);
|
sendMessage(EVENT_SUBSCRIPTIONS_CHANGED, TOKEN_ALL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,12 +59,17 @@ public class VcnGatewayConnectionConfigTest {
|
|||||||
|
|
||||||
// Public for use in VcnGatewayConnectionTest
|
// Public for use in VcnGatewayConnectionTest
|
||||||
public static VcnGatewayConnectionConfig buildTestConfig() {
|
public static VcnGatewayConnectionConfig buildTestConfig() {
|
||||||
|
return buildTestConfigWithExposedCaps(EXPOSED_CAPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public for use in VcnGatewayConnectionTest
|
||||||
|
public static VcnGatewayConnectionConfig buildTestConfigWithExposedCaps(int... exposedCaps) {
|
||||||
final VcnGatewayConnectionConfig.Builder builder =
|
final VcnGatewayConnectionConfig.Builder builder =
|
||||||
new VcnGatewayConnectionConfig.Builder()
|
new VcnGatewayConnectionConfig.Builder()
|
||||||
.setRetryInterval(RETRY_INTERVALS_MS)
|
.setRetryInterval(RETRY_INTERVALS_MS)
|
||||||
.setMaxMtu(MAX_MTU);
|
.setMaxMtu(MAX_MTU);
|
||||||
|
|
||||||
for (int caps : EXPOSED_CAPS) {
|
for (int caps : exposedCaps) {
|
||||||
builder.addExposedCapability(caps);
|
builder.addExposedCapability(caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ import android.telephony.TelephonyManager;
|
|||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
|
import com.android.server.VcnManagementService.VcnSafemodeCallback;
|
||||||
import com.android.server.vcn.TelephonySubscriptionTracker;
|
import com.android.server.vcn.TelephonySubscriptionTracker;
|
||||||
import com.android.server.vcn.Vcn;
|
import com.android.server.vcn.Vcn;
|
||||||
import com.android.server.vcn.VcnContext;
|
import com.android.server.vcn.VcnContext;
|
||||||
@@ -142,6 +143,9 @@ public class VcnManagementServiceTest {
|
|||||||
private final TelephonySubscriptionTracker mSubscriptionTracker =
|
private final TelephonySubscriptionTracker mSubscriptionTracker =
|
||||||
mock(TelephonySubscriptionTracker.class);
|
mock(TelephonySubscriptionTracker.class);
|
||||||
|
|
||||||
|
private final ArgumentCaptor<VcnSafemodeCallback> mSafemodeCallbackCaptor =
|
||||||
|
ArgumentCaptor.forClass(VcnSafemodeCallback.class);
|
||||||
|
|
||||||
private final VcnManagementService mVcnMgmtSvc;
|
private final VcnManagementService mVcnMgmtSvc;
|
||||||
|
|
||||||
private final IVcnUnderlyingNetworkPolicyListener mMockPolicyListener =
|
private final IVcnUnderlyingNetworkPolicyListener mMockPolicyListener =
|
||||||
@@ -184,7 +188,7 @@ public class VcnManagementServiceTest {
|
|||||||
doAnswer((invocation) -> {
|
doAnswer((invocation) -> {
|
||||||
// Mock-within a doAnswer is safe, because it doesn't actually run nested.
|
// Mock-within a doAnswer is safe, because it doesn't actually run nested.
|
||||||
return mock(Vcn.class);
|
return mock(Vcn.class);
|
||||||
}).when(mMockDeps).newVcn(any(), any(), any(), any());
|
}).when(mMockDeps).newVcn(any(), any(), any(), any(), any());
|
||||||
|
|
||||||
final PersistableBundle bundle =
|
final PersistableBundle bundle =
|
||||||
PersistableBundleUtils.fromMap(
|
PersistableBundleUtils.fromMap(
|
||||||
@@ -307,7 +311,7 @@ public class VcnManagementServiceTest {
|
|||||||
TelephonySubscriptionSnapshot snapshot =
|
TelephonySubscriptionSnapshot snapshot =
|
||||||
triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1));
|
triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1));
|
||||||
verify(mMockDeps)
|
verify(mMockDeps)
|
||||||
.newVcn(eq(mVcnContext), eq(TEST_UUID_1), eq(TEST_VCN_CONFIG), eq(snapshot));
|
.newVcn(eq(mVcnContext), eq(TEST_UUID_1), eq(TEST_VCN_CONFIG), eq(snapshot), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -485,7 +489,8 @@ public class VcnManagementServiceTest {
|
|||||||
eq(mVcnContext),
|
eq(mVcnContext),
|
||||||
eq(TEST_UUID_2),
|
eq(TEST_UUID_2),
|
||||||
eq(TEST_VCN_CONFIG),
|
eq(TEST_VCN_CONFIG),
|
||||||
eq(TelephonySubscriptionSnapshot.EMPTY_SNAPSHOT));
|
eq(TelephonySubscriptionSnapshot.EMPTY_SNAPSHOT),
|
||||||
|
any());
|
||||||
|
|
||||||
// Verify Vcn is updated if it was previously started
|
// Verify Vcn is updated if it was previously started
|
||||||
mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME);
|
mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME);
|
||||||
@@ -634,4 +639,25 @@ public class VcnManagementServiceTest {
|
|||||||
|
|
||||||
verify(mMockPolicyListener).onPolicyChanged();
|
verify(mMockPolicyListener).onPolicyChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVcnSafemodeCallbackOnEnteredSafemode() throws Exception {
|
||||||
|
TelephonySubscriptionSnapshot snapshot =
|
||||||
|
triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1));
|
||||||
|
verify(mMockDeps)
|
||||||
|
.newVcn(
|
||||||
|
eq(mVcnContext),
|
||||||
|
eq(TEST_UUID_1),
|
||||||
|
eq(TEST_VCN_CONFIG),
|
||||||
|
eq(snapshot),
|
||||||
|
mSafemodeCallbackCaptor.capture());
|
||||||
|
|
||||||
|
mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
|
||||||
|
|
||||||
|
VcnSafemodeCallback safemodeCallback = mSafemodeCallbackCaptor.getValue();
|
||||||
|
safemodeCallback.onEnteredSafemode();
|
||||||
|
|
||||||
|
assertFalse(mVcnMgmtSvc.getAllVcns().get(TEST_UUID_1).isActive());
|
||||||
|
verify(mMockPolicyListener).onPolicyChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,12 @@ public class VcnGatewayConnectionDisconnectedStateTest extends VcnGatewayConnect
|
|||||||
public void testEnterWhileNotRunningTriggersQuit() throws Exception {
|
public void testEnterWhileNotRunningTriggersQuit() throws Exception {
|
||||||
final VcnGatewayConnection vgc =
|
final VcnGatewayConnection vgc =
|
||||||
new VcnGatewayConnection(
|
new VcnGatewayConnection(
|
||||||
mVcnContext, TEST_SUB_GRP, TEST_SUBSCRIPTION_SNAPSHOT, mConfig, mDeps);
|
mVcnContext,
|
||||||
|
TEST_SUB_GRP,
|
||||||
|
TEST_SUBSCRIPTION_SNAPSHOT,
|
||||||
|
mConfig,
|
||||||
|
mGatewayStatusCallback,
|
||||||
|
mDeps);
|
||||||
|
|
||||||
vgc.setIsRunning(false);
|
vgc.setIsRunning(false);
|
||||||
vgc.transitionTo(vgc.mDisconnectedState);
|
vgc.transitionTo(vgc.mDisconnectedState);
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import android.os.test.TestLooper;
|
|||||||
|
|
||||||
import com.android.server.IpSecService;
|
import com.android.server.IpSecService;
|
||||||
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
||||||
|
import com.android.server.vcn.Vcn.VcnGatewayStatusCallback;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
@@ -80,6 +81,7 @@ public class VcnGatewayConnectionTestBase {
|
|||||||
@NonNull protected final VcnNetworkProvider mVcnNetworkProvider;
|
@NonNull protected final VcnNetworkProvider mVcnNetworkProvider;
|
||||||
@NonNull protected final VcnContext mVcnContext;
|
@NonNull protected final VcnContext mVcnContext;
|
||||||
@NonNull protected final VcnGatewayConnectionConfig mConfig;
|
@NonNull protected final VcnGatewayConnectionConfig mConfig;
|
||||||
|
@NonNull protected final VcnGatewayStatusCallback mGatewayStatusCallback;
|
||||||
@NonNull protected final VcnGatewayConnection.Dependencies mDeps;
|
@NonNull protected final VcnGatewayConnection.Dependencies mDeps;
|
||||||
@NonNull protected final UnderlyingNetworkTracker mUnderlyingNetworkTracker;
|
@NonNull protected final UnderlyingNetworkTracker mUnderlyingNetworkTracker;
|
||||||
|
|
||||||
@@ -94,6 +96,7 @@ public class VcnGatewayConnectionTestBase {
|
|||||||
mVcnNetworkProvider = mock(VcnNetworkProvider.class);
|
mVcnNetworkProvider = mock(VcnNetworkProvider.class);
|
||||||
mVcnContext = mock(VcnContext.class);
|
mVcnContext = mock(VcnContext.class);
|
||||||
mConfig = VcnGatewayConnectionConfigTest.buildTestConfig();
|
mConfig = VcnGatewayConnectionConfigTest.buildTestConfig();
|
||||||
|
mGatewayStatusCallback = mock(VcnGatewayStatusCallback.class);
|
||||||
mDeps = mock(VcnGatewayConnection.Dependencies.class);
|
mDeps = mock(VcnGatewayConnection.Dependencies.class);
|
||||||
mUnderlyingNetworkTracker = mock(UnderlyingNetworkTracker.class);
|
mUnderlyingNetworkTracker = mock(UnderlyingNetworkTracker.class);
|
||||||
|
|
||||||
@@ -123,7 +126,12 @@ public class VcnGatewayConnectionTestBase {
|
|||||||
|
|
||||||
mGatewayConnection =
|
mGatewayConnection =
|
||||||
new VcnGatewayConnection(
|
new VcnGatewayConnection(
|
||||||
mVcnContext, TEST_SUB_GRP, TEST_SUBSCRIPTION_SNAPSHOT, mConfig, mDeps);
|
mVcnContext,
|
||||||
|
TEST_SUB_GRP,
|
||||||
|
TEST_SUBSCRIPTION_SNAPSHOT,
|
||||||
|
mConfig,
|
||||||
|
mGatewayStatusCallback,
|
||||||
|
mDeps);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IpSecTransform makeDummyIpSecTransform() throws Exception {
|
protected IpSecTransform makeDummyIpSecTransform() throws Exception {
|
||||||
|
|||||||
@@ -16,22 +16,27 @@
|
|||||||
|
|
||||||
package com.android.server.vcn;
|
package com.android.server.vcn;
|
||||||
|
|
||||||
|
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.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;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.NetworkRequest;
|
import android.net.NetworkRequest;
|
||||||
import android.net.vcn.VcnConfig;
|
import android.net.vcn.VcnConfig;
|
||||||
|
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 com.android.server.VcnManagementService.VcnSafemodeCallback;
|
||||||
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
||||||
|
import com.android.server.vcn.Vcn.VcnGatewayStatusCallback;
|
||||||
import com.android.server.vcn.VcnNetworkProvider.NetworkRequestListener;
|
import com.android.server.vcn.VcnNetworkProvider.NetworkRequestListener;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -51,9 +56,13 @@ public class VcnTest {
|
|||||||
private VcnContext mVcnContext;
|
private VcnContext mVcnContext;
|
||||||
private TelephonySubscriptionSnapshot mSubscriptionSnapshot;
|
private TelephonySubscriptionSnapshot mSubscriptionSnapshot;
|
||||||
private VcnNetworkProvider mVcnNetworkProvider;
|
private VcnNetworkProvider mVcnNetworkProvider;
|
||||||
|
private VcnSafemodeCallback mVcnSafemodeCallback;
|
||||||
private Vcn.Dependencies mDeps;
|
private Vcn.Dependencies mDeps;
|
||||||
|
|
||||||
|
private ArgumentCaptor<VcnGatewayStatusCallback> mGatewayStatusCallbackCaptor;
|
||||||
|
|
||||||
private TestLooper mTestLooper;
|
private TestLooper mTestLooper;
|
||||||
|
private VcnGatewayConnectionConfig mGatewayConnectionConfig;
|
||||||
private VcnConfig mConfig;
|
private VcnConfig mConfig;
|
||||||
private Vcn mVcn;
|
private Vcn mVcn;
|
||||||
|
|
||||||
@@ -63,6 +72,7 @@ public class VcnTest {
|
|||||||
mVcnContext = mock(VcnContext.class);
|
mVcnContext = mock(VcnContext.class);
|
||||||
mSubscriptionSnapshot = mock(TelephonySubscriptionSnapshot.class);
|
mSubscriptionSnapshot = mock(TelephonySubscriptionSnapshot.class);
|
||||||
mVcnNetworkProvider = mock(VcnNetworkProvider.class);
|
mVcnNetworkProvider = mock(VcnNetworkProvider.class);
|
||||||
|
mVcnSafemodeCallback = mock(VcnSafemodeCallback.class);
|
||||||
mDeps = mock(Vcn.Dependencies.class);
|
mDeps = mock(Vcn.Dependencies.class);
|
||||||
|
|
||||||
mTestLooper = new TestLooper();
|
mTestLooper = new TestLooper();
|
||||||
@@ -76,15 +86,26 @@ public class VcnTest {
|
|||||||
doAnswer((invocation) -> {
|
doAnswer((invocation) -> {
|
||||||
// Mock-within a doAnswer is safe, because it doesn't actually run nested.
|
// Mock-within a doAnswer is safe, because it doesn't actually run nested.
|
||||||
return mock(VcnGatewayConnection.class);
|
return mock(VcnGatewayConnection.class);
|
||||||
}).when(mDeps).newVcnGatewayConnection(any(), any(), any(), any());
|
}).when(mDeps).newVcnGatewayConnection(any(), any(), any(), any(), any());
|
||||||
|
|
||||||
mConfig =
|
mGatewayStatusCallbackCaptor = ArgumentCaptor.forClass(VcnGatewayStatusCallback.class);
|
||||||
new VcnConfig.Builder(mContext)
|
|
||||||
.addGatewayConnectionConfig(
|
|
||||||
VcnGatewayConnectionConfigTest.buildTestConfig())
|
|
||||||
.build();
|
|
||||||
|
|
||||||
mVcn = new Vcn(mVcnContext, TEST_SUB_GROUP, mConfig, mSubscriptionSnapshot, mDeps);
|
final VcnConfig.Builder configBuilder = new VcnConfig.Builder(mContext);
|
||||||
|
for (final int capability : VcnGatewayConnectionConfigTest.EXPOSED_CAPS) {
|
||||||
|
configBuilder.addGatewayConnectionConfig(
|
||||||
|
VcnGatewayConnectionConfigTest.buildTestConfigWithExposedCaps(capability));
|
||||||
|
}
|
||||||
|
configBuilder.addGatewayConnectionConfig(VcnGatewayConnectionConfigTest.buildTestConfig());
|
||||||
|
mConfig = configBuilder.build();
|
||||||
|
|
||||||
|
mVcn =
|
||||||
|
new Vcn(
|
||||||
|
mVcnContext,
|
||||||
|
TEST_SUB_GROUP,
|
||||||
|
mConfig,
|
||||||
|
mSubscriptionSnapshot,
|
||||||
|
mVcnSafemodeCallback,
|
||||||
|
mDeps);
|
||||||
}
|
}
|
||||||
|
|
||||||
private NetworkRequestListener verifyAndGetRequestListener() {
|
private NetworkRequestListener verifyAndGetRequestListener() {
|
||||||
@@ -95,23 +116,22 @@ public class VcnTest {
|
|||||||
return mNetworkRequestListenerCaptor.getValue();
|
return mNetworkRequestListenerCaptor.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
private NetworkRequest getNetworkRequestWithCapabilities(int[] networkCapabilities) {
|
private void startVcnGatewayWithCapabilities(
|
||||||
final NetworkRequest.Builder builder = new NetworkRequest.Builder();
|
NetworkRequestListener requestListener, int... netCapabilities) {
|
||||||
for (final int netCapability : networkCapabilities) {
|
final NetworkRequest.Builder requestBuilder = new NetworkRequest.Builder();
|
||||||
builder.addCapability(netCapability);
|
for (final int netCapability : netCapabilities) {
|
||||||
|
requestBuilder.addCapability(netCapability);
|
||||||
}
|
}
|
||||||
return builder.build();
|
|
||||||
|
requestListener.onNetworkRequested(requestBuilder.build(), NETWORK_SCORE, PROVIDER_ID);
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSubscriptionSnapshotUpdatesVcnGatewayConnections() {
|
public void testSubscriptionSnapshotUpdatesVcnGatewayConnections() {
|
||||||
final NetworkRequestListener requestListener = verifyAndGetRequestListener();
|
final NetworkRequestListener requestListener = verifyAndGetRequestListener();
|
||||||
|
startVcnGatewayWithCapabilities(
|
||||||
requestListener.onNetworkRequested(
|
requestListener, VcnGatewayConnectionConfigTest.EXPOSED_CAPS);
|
||||||
getNetworkRequestWithCapabilities(VcnGatewayConnectionConfigTest.EXPOSED_CAPS),
|
|
||||||
NETWORK_SCORE,
|
|
||||||
PROVIDER_ID);
|
|
||||||
mTestLooper.dispatchAll();
|
|
||||||
|
|
||||||
final Set<VcnGatewayConnection> gatewayConnections = mVcn.getVcnGatewayConnections();
|
final Set<VcnGatewayConnection> gatewayConnections = mVcn.getVcnGatewayConnections();
|
||||||
assertFalse(gatewayConnections.isEmpty());
|
assertFalse(gatewayConnections.isEmpty());
|
||||||
@@ -126,4 +146,38 @@ public class VcnTest {
|
|||||||
verify(gateway).updateSubscriptionSnapshot(eq(updatedSnapshot));
|
verify(gateway).updateSubscriptionSnapshot(eq(updatedSnapshot));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGatewayEnteringSafemodeNotifiesVcn() {
|
||||||
|
final NetworkRequestListener requestListener = verifyAndGetRequestListener();
|
||||||
|
for (final int capability : VcnGatewayConnectionConfigTest.EXPOSED_CAPS) {
|
||||||
|
startVcnGatewayWithCapabilities(requestListener, capability);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each Capability in EXPOSED_CAPS was split into a separate VcnGatewayConnection in #setUp.
|
||||||
|
// Expect one VcnGatewayConnection per capability.
|
||||||
|
final int numExpectedGateways = VcnGatewayConnectionConfigTest.EXPOSED_CAPS.length;
|
||||||
|
|
||||||
|
final Set<VcnGatewayConnection> gatewayConnections = mVcn.getVcnGatewayConnections();
|
||||||
|
assertEquals(numExpectedGateways, gatewayConnections.size());
|
||||||
|
verify(mDeps, times(numExpectedGateways))
|
||||||
|
.newVcnGatewayConnection(
|
||||||
|
eq(mVcnContext),
|
||||||
|
eq(TEST_SUB_GROUP),
|
||||||
|
eq(mSubscriptionSnapshot),
|
||||||
|
any(),
|
||||||
|
mGatewayStatusCallbackCaptor.capture());
|
||||||
|
|
||||||
|
// Doesn't matter which callback this gets - any Gateway entering Safemode should shut down
|
||||||
|
// all Gateways
|
||||||
|
final VcnGatewayStatusCallback statusCallback = mGatewayStatusCallbackCaptor.getValue();
|
||||||
|
statusCallback.onEnteredSafemode();
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
for (final VcnGatewayConnection gatewayConnection : gatewayConnections) {
|
||||||
|
verify(gatewayConnection).teardownAsynchronously();
|
||||||
|
}
|
||||||
|
verify(mVcnNetworkProvider).unregisterListener(requestListener);
|
||||||
|
verify(mVcnSafemodeCallback).onEnteredSafemode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user