Merge changes I0cadd145,I3be3cac4,I9ea6e9e8
* changes: Correct comment for safe mode alarm in VcnGatewayConnection. Implement VCN error callback use. Define VcnStatusCallback#onGatewayConnectionError callback.
This commit is contained in:
@@ -19,4 +19,9 @@ package android.net.vcn;
|
|||||||
/** @hide */
|
/** @hide */
|
||||||
interface IVcnStatusCallback {
|
interface IVcnStatusCallback {
|
||||||
void onEnteredSafeMode();
|
void onEnteredSafeMode();
|
||||||
|
void onGatewayConnectionError(
|
||||||
|
in int[] gatewayNetworkCapabilities,
|
||||||
|
int errorCode,
|
||||||
|
in String exceptionClass,
|
||||||
|
in String exceptionMessage);
|
||||||
}
|
}
|
||||||
@@ -17,7 +17,9 @@ package android.net.vcn;
|
|||||||
|
|
||||||
import static java.util.Objects.requireNonNull;
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
import android.annotation.IntDef;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.annotation.RequiresPermission;
|
import android.annotation.RequiresPermission;
|
||||||
import android.annotation.SystemService;
|
import android.annotation.SystemService;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -32,6 +34,8 @@ import com.android.internal.annotations.VisibleForTesting;
|
|||||||
import com.android.internal.annotations.VisibleForTesting.Visibility;
|
import com.android.internal.annotations.VisibleForTesting.Visibility;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
@@ -262,6 +266,42 @@ public class VcnManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@IntDef({
|
||||||
|
VCN_ERROR_CODE_INTERNAL_ERROR,
|
||||||
|
VCN_ERROR_CODE_CONFIG_ERROR,
|
||||||
|
VCN_ERROR_CODE_NETWORK_ERROR
|
||||||
|
})
|
||||||
|
public @interface VcnErrorCode {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value indicating that an internal failure occurred in this Gateway Connection.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final int VCN_ERROR_CODE_INTERNAL_ERROR = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value indicating that an error with this Gateway Connection's configuration occurred.
|
||||||
|
*
|
||||||
|
* <p>For example, this error code will be returned after authentication failures.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final int VCN_ERROR_CODE_CONFIG_ERROR = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value indicating that a Network error occurred with this Gateway Connection.
|
||||||
|
*
|
||||||
|
* <p>For example, this error code will be returned if an underlying {@link android.net.Network}
|
||||||
|
* for this Gateway Connection is lost, or if an error occurs while resolving the connection
|
||||||
|
* endpoint address.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final int VCN_ERROR_CODE_NETWORK_ERROR = 2;
|
||||||
|
|
||||||
// TODO: make VcnStatusCallback @SystemApi
|
// TODO: make VcnStatusCallback @SystemApi
|
||||||
/**
|
/**
|
||||||
* VcnStatusCallback is the interface for Carrier apps to receive updates for their VCNs.
|
* VcnStatusCallback is the interface for Carrier apps to receive updates for their VCNs.
|
||||||
@@ -285,6 +325,24 @@ public class VcnManager {
|
|||||||
* via {@link #setVcnConfig(ParcelUuid, VcnConfig)}.
|
* via {@link #setVcnConfig(ParcelUuid, VcnConfig)}.
|
||||||
*/
|
*/
|
||||||
public abstract void onEnteredSafeMode();
|
public abstract void onEnteredSafeMode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when a VCN Gateway Connection corresponding to this callback's subscription
|
||||||
|
* encounters an error.
|
||||||
|
*
|
||||||
|
* @param networkCapabilities an array of underlying NetworkCapabilities for the Gateway
|
||||||
|
* Connection that encountered the error for identification purposes. These will be a
|
||||||
|
* sorted list with no duplicates, matching one of the {@link
|
||||||
|
* VcnGatewayConnectionConfig}s set in the {@link VcnConfig} for this subscription
|
||||||
|
* group.
|
||||||
|
* @param errorCode {@link VcnErrorCode} to indicate the error that occurred
|
||||||
|
* @param detail Throwable to provide additional information about the error, or {@code
|
||||||
|
* null} if none
|
||||||
|
*/
|
||||||
|
public abstract void onGatewayConnectionError(
|
||||||
|
@NonNull int[] networkCapabilities,
|
||||||
|
@VcnErrorCode int errorCode,
|
||||||
|
@Nullable Throwable detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -385,11 +443,12 @@ public class VcnManager {
|
|||||||
*
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
private class VcnStatusCallbackBinder extends IVcnStatusCallback.Stub {
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
|
public static class VcnStatusCallbackBinder extends IVcnStatusCallback.Stub {
|
||||||
@NonNull private final Executor mExecutor;
|
@NonNull private final Executor mExecutor;
|
||||||
@NonNull private final VcnStatusCallback mCallback;
|
@NonNull private final VcnStatusCallback mCallback;
|
||||||
|
|
||||||
private VcnStatusCallbackBinder(
|
public VcnStatusCallbackBinder(
|
||||||
@NonNull Executor executor, @NonNull VcnStatusCallback callback) {
|
@NonNull Executor executor, @NonNull VcnStatusCallback callback) {
|
||||||
mExecutor = executor;
|
mExecutor = executor;
|
||||||
mCallback = callback;
|
mCallback = callback;
|
||||||
@@ -400,5 +459,36 @@ public class VcnManager {
|
|||||||
Binder.withCleanCallingIdentity(
|
Binder.withCleanCallingIdentity(
|
||||||
() -> mExecutor.execute(() -> mCallback.onEnteredSafeMode()));
|
() -> mExecutor.execute(() -> mCallback.onEnteredSafeMode()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(b/180521637): use ServiceSpecificException for safer Exception 'parceling'
|
||||||
|
@Override
|
||||||
|
public void onGatewayConnectionError(
|
||||||
|
@NonNull int[] networkCapabilities,
|
||||||
|
@VcnErrorCode int errorCode,
|
||||||
|
@Nullable String exceptionClass,
|
||||||
|
@Nullable String exceptionMessage) {
|
||||||
|
final Throwable cause = createThrowableByClassName(exceptionClass, exceptionMessage);
|
||||||
|
|
||||||
|
Binder.withCleanCallingIdentity(
|
||||||
|
() ->
|
||||||
|
mExecutor.execute(
|
||||||
|
() ->
|
||||||
|
mCallback.onGatewayConnectionError(
|
||||||
|
networkCapabilities, errorCode, cause)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Throwable createThrowableByClassName(
|
||||||
|
@Nullable String className, @Nullable String message) {
|
||||||
|
if (className == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Class<?> c = Class.forName(className);
|
||||||
|
return (Throwable) c.getConstructor(String.class).newInstance(message);
|
||||||
|
} catch (ReflectiveOperationException | ClassCastException e) {
|
||||||
|
return new RuntimeException(className + ": " + message);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import android.net.vcn.IVcnManagementService;
|
|||||||
import android.net.vcn.IVcnStatusCallback;
|
import android.net.vcn.IVcnStatusCallback;
|
||||||
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
|
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
|
||||||
import android.net.vcn.VcnConfig;
|
import android.net.vcn.VcnConfig;
|
||||||
|
import android.net.vcn.VcnManager.VcnErrorCode;
|
||||||
import android.net.vcn.VcnUnderlyingNetworkPolicy;
|
import android.net.vcn.VcnUnderlyingNetworkPolicy;
|
||||||
import android.net.wifi.WifiInfo;
|
import android.net.wifi.WifiInfo;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
@@ -304,8 +305,8 @@ public class VcnManagementService extends IVcnManagementService.Stub {
|
|||||||
@NonNull ParcelUuid subscriptionGroup,
|
@NonNull ParcelUuid subscriptionGroup,
|
||||||
@NonNull VcnConfig config,
|
@NonNull VcnConfig config,
|
||||||
@NonNull TelephonySubscriptionSnapshot snapshot,
|
@NonNull TelephonySubscriptionSnapshot snapshot,
|
||||||
@NonNull VcnSafeModeCallback safeModeCallback) {
|
@NonNull VcnCallback vcnCallback) {
|
||||||
return new Vcn(vcnContext, subscriptionGroup, config, snapshot, safeModeCallback);
|
return new Vcn(vcnContext, subscriptionGroup, config, snapshot, vcnCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the subId indicated by the given {@link WifiInfo}. */
|
/** Gets the subId indicated by the given {@link WifiInfo}. */
|
||||||
@@ -457,12 +458,10 @@ 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 VcnSafeModeCallbackImpl safeModeCallback =
|
final VcnCallbackImpl vcnCallback = new VcnCallbackImpl(subscriptionGroup);
|
||||||
new VcnSafeModeCallbackImpl(subscriptionGroup);
|
|
||||||
|
|
||||||
final Vcn newInstance =
|
final Vcn newInstance =
|
||||||
mDeps.newVcn(
|
mDeps.newVcn(mVcnContext, subscriptionGroup, config, mLastSnapshot, vcnCallback);
|
||||||
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
|
||||||
@@ -784,20 +783,47 @@ 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 signalling when a Vcn has entered safe mode. */
|
/** Callback for Vcn signals sent up to VcnManagementService. */
|
||||||
public interface VcnSafeModeCallback {
|
public interface VcnCallback {
|
||||||
/** Called by a Vcn to signal that it has entered safe mode. */
|
/** Called by a Vcn to signal that it has entered safe mode. */
|
||||||
void onEnteredSafeMode();
|
void onEnteredSafeMode();
|
||||||
|
|
||||||
|
/** Called by a Vcn to signal that an error occurred. */
|
||||||
|
void onGatewayConnectionError(
|
||||||
|
@NonNull int[] networkCapabilities,
|
||||||
|
@VcnErrorCode int errorCode,
|
||||||
|
@Nullable String exceptionClass,
|
||||||
|
@Nullable String exceptionMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** VcnSafeModeCallback is used by Vcns to notify VcnManagementService on entering safe mode. */
|
/** VcnCallbackImpl for Vcn signals sent up to VcnManagementService. */
|
||||||
private class VcnSafeModeCallbackImpl implements VcnSafeModeCallback {
|
private class VcnCallbackImpl implements VcnCallback {
|
||||||
@NonNull private final ParcelUuid mSubGroup;
|
@NonNull private final ParcelUuid mSubGroup;
|
||||||
|
|
||||||
private VcnSafeModeCallbackImpl(@NonNull final ParcelUuid subGroup) {
|
private VcnCallbackImpl(@NonNull final ParcelUuid subGroup) {
|
||||||
mSubGroup = Objects.requireNonNull(subGroup, "Missing subGroup");
|
mSubGroup = Objects.requireNonNull(subGroup, "Missing subGroup");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isCallbackPermissioned(@NonNull VcnStatusCallbackInfo cbInfo) {
|
||||||
|
if (!mSubGroup.equals(cbInfo.mSubGroup)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mLastSnapshot.packageHasPermissionsForSubscriptionGroup(
|
||||||
|
mSubGroup, cbInfo.mPkgName)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mLocationPermissionChecker.checkLocationPermission(
|
||||||
|
cbInfo.mPkgName,
|
||||||
|
"VcnStatusCallback" /* featureId */,
|
||||||
|
cbInfo.mUid,
|
||||||
|
null /* message */)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnteredSafeMode() {
|
public void onEnteredSafeMode() {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
@@ -810,23 +836,36 @@ public class VcnManagementService extends IVcnManagementService.Stub {
|
|||||||
|
|
||||||
// Notify all registered StatusCallbacks for this subGroup
|
// Notify all registered StatusCallbacks for this subGroup
|
||||||
for (VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
|
for (VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
|
||||||
if (!mSubGroup.equals(cbInfo.mSubGroup)) {
|
if (isCallbackPermissioned(cbInfo)) {
|
||||||
continue;
|
Binder.withCleanCallingIdentity(() -> cbInfo.mCallback.onEnteredSafeMode());
|
||||||
}
|
|
||||||
if (!mLastSnapshot.packageHasPermissionsForSubscriptionGroup(
|
|
||||||
mSubGroup, cbInfo.mPkgName)) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!mLocationPermissionChecker.checkLocationPermission(
|
@Override
|
||||||
cbInfo.mPkgName,
|
public void onGatewayConnectionError(
|
||||||
"VcnStatusCallback" /* featureId */,
|
@NonNull int[] networkCapabilities,
|
||||||
cbInfo.mUid,
|
@VcnErrorCode int errorCode,
|
||||||
null /* message */)) {
|
@Nullable String exceptionClass,
|
||||||
continue;
|
@Nullable String exceptionMessage) {
|
||||||
}
|
synchronized (mLock) {
|
||||||
|
// Ignore if this subscription group doesn't exist anymore
|
||||||
|
if (!mVcns.containsKey(mSubGroup)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Binder.withCleanCallingIdentity(() -> cbInfo.mCallback.onEnteredSafeMode());
|
// Notify all registered StatusCallbacks for this subGroup
|
||||||
|
for (VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
|
||||||
|
if (isCallbackPermissioned(cbInfo)) {
|
||||||
|
Binder.withCleanCallingIdentity(
|
||||||
|
() ->
|
||||||
|
cbInfo.mCallback.onGatewayConnectionError(
|
||||||
|
networkCapabilities,
|
||||||
|
errorCode,
|
||||||
|
exceptionClass,
|
||||||
|
exceptionMessage));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,10 +19,12 @@ package com.android.server.vcn;
|
|||||||
import static com.android.server.VcnManagementService.VDBG;
|
import static com.android.server.VcnManagementService.VDBG;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
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.VcnGatewayConnectionConfig;
|
||||||
|
import android.net.vcn.VcnManager.VcnErrorCode;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.ParcelUuid;
|
import android.os.ParcelUuid;
|
||||||
@@ -30,7 +32,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.VcnManagementService.VcnCallback;
|
||||||
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -97,7 +99,7 @@ public class Vcn extends Handler {
|
|||||||
@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 private final VcnCallback mVcnCallback;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private final Map<VcnGatewayConnectionConfig, VcnGatewayConnection> mVcnGatewayConnections =
|
private final Map<VcnGatewayConnectionConfig, VcnGatewayConnection> mVcnGatewayConnections =
|
||||||
@@ -125,14 +127,8 @@ 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 VcnCallback vcnCallback) {
|
||||||
this(
|
this(vcnContext, subscriptionGroup, config, snapshot, vcnCallback, new Dependencies());
|
||||||
vcnContext,
|
|
||||||
subscriptionGroup,
|
|
||||||
config,
|
|
||||||
snapshot,
|
|
||||||
vcnSafeModeCallback,
|
|
||||||
new Dependencies());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
@@ -141,13 +137,12 @@ 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 VcnCallback vcnCallback,
|
||||||
@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 =
|
mVcnCallback = Objects.requireNonNull(vcnCallback, "Missing vcnCallback");
|
||||||
Objects.requireNonNull(vcnSafeModeCallback, "Missing vcnSafeModeCallback");
|
|
||||||
mDeps = Objects.requireNonNull(deps, "Missing deps");
|
mDeps = Objects.requireNonNull(deps, "Missing deps");
|
||||||
mRequestListener = new VcnNetworkRequestListener();
|
mRequestListener = new VcnNetworkRequestListener();
|
||||||
|
|
||||||
@@ -246,7 +241,7 @@ public class Vcn extends Handler {
|
|||||||
private void handleEnterSafeMode() {
|
private void handleEnterSafeMode() {
|
||||||
handleTeardown();
|
handleTeardown();
|
||||||
|
|
||||||
mVcnSafeModeCallback.onEnteredSafeMode();
|
mVcnCallback.onEnteredSafeMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleNetworkRequested(
|
private void handleNetworkRequested(
|
||||||
@@ -337,6 +332,13 @@ public class Vcn extends Handler {
|
|||||||
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 has entered safe mode. */
|
||||||
void onEnteredSafeMode();
|
void onEnteredSafeMode();
|
||||||
|
|
||||||
|
/** Callback by a VcnGatewayConnection to indicate that an error occurred. */
|
||||||
|
void onGatewayConnectionError(
|
||||||
|
@NonNull int[] networkCapabilities,
|
||||||
|
@VcnErrorCode int errorCode,
|
||||||
|
@Nullable String exceptionClass,
|
||||||
|
@Nullable String exceptionMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class VcnGatewayStatusCallbackImpl implements VcnGatewayStatusCallback {
|
private class VcnGatewayStatusCallbackImpl implements VcnGatewayStatusCallback {
|
||||||
@@ -344,6 +346,16 @@ public class Vcn extends Handler {
|
|||||||
public void onEnteredSafeMode() {
|
public void onEnteredSafeMode() {
|
||||||
sendMessage(obtainMessage(MSG_CMD_ENTER_SAFE_MODE));
|
sendMessage(obtainMessage(MSG_CMD_ENTER_SAFE_MODE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onGatewayConnectionError(
|
||||||
|
@NonNull int[] networkCapabilities,
|
||||||
|
@VcnErrorCode int errorCode,
|
||||||
|
@Nullable String exceptionClass,
|
||||||
|
@Nullable String exceptionMessage) {
|
||||||
|
mVcnCallback.onGatewayConnectionError(
|
||||||
|
networkCapabilities, errorCode, exceptionClass, exceptionMessage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** External dependencies used by Vcn, for injection in tests */
|
/** External dependencies used by Vcn, for injection in tests */
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
|
|||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
|
||||||
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
||||||
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
||||||
|
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_CONFIG_ERROR;
|
||||||
|
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_INTERNAL_ERROR;
|
||||||
|
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_NETWORK_ERROR;
|
||||||
|
|
||||||
import static com.android.server.VcnManagementService.VDBG;
|
import static com.android.server.VcnManagementService.VDBG;
|
||||||
|
|
||||||
@@ -52,7 +55,9 @@ import android.net.ipsec.ike.IkeSession;
|
|||||||
import android.net.ipsec.ike.IkeSessionCallback;
|
import android.net.ipsec.ike.IkeSessionCallback;
|
||||||
import android.net.ipsec.ike.IkeSessionConfiguration;
|
import android.net.ipsec.ike.IkeSessionConfiguration;
|
||||||
import android.net.ipsec.ike.IkeSessionParams;
|
import android.net.ipsec.ike.IkeSessionParams;
|
||||||
|
import android.net.ipsec.ike.exceptions.AuthenticationFailedException;
|
||||||
import android.net.ipsec.ike.exceptions.IkeException;
|
import android.net.ipsec.ike.exceptions.IkeException;
|
||||||
|
import android.net.ipsec.ike.exceptions.IkeInternalException;
|
||||||
import android.net.ipsec.ike.exceptions.IkeProtocolException;
|
import android.net.ipsec.ike.exceptions.IkeProtocolException;
|
||||||
import android.net.vcn.VcnGatewayConnectionConfig;
|
import android.net.vcn.VcnGatewayConnectionConfig;
|
||||||
import android.net.vcn.VcnTransportInfo;
|
import android.net.vcn.VcnTransportInfo;
|
||||||
@@ -951,15 +956,68 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
removeEqualMessages(EVENT_SAFE_MODE_TIMEOUT_EXCEEDED);
|
removeEqualMessages(EVENT_SAFE_MODE_TIMEOUT_EXCEEDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sessionLost(int token, @Nullable Exception exception) {
|
private void sessionLostWithoutCallback(int token, @Nullable Exception exception) {
|
||||||
sendMessageAndAcquireWakeLock(
|
sendMessageAndAcquireWakeLock(
|
||||||
EVENT_SESSION_LOST, token, new EventSessionLostInfo(exception));
|
EVENT_SESSION_LOST, token, new EventSessionLostInfo(exception));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sessionLost(int token, @Nullable Exception exception) {
|
||||||
|
// Only notify mGatewayStatusCallback if the session was lost with an error. All
|
||||||
|
// authentication and DNS failures are sent through
|
||||||
|
// IkeSessionCallback.onClosedExceptionally(), which calls sessionClosed()
|
||||||
|
if (exception != null) {
|
||||||
|
mGatewayStatusCallback.onGatewayConnectionError(
|
||||||
|
mConnectionConfig.getRequiredUnderlyingCapabilities(),
|
||||||
|
VCN_ERROR_CODE_INTERNAL_ERROR,
|
||||||
|
"java.lang.RuntimeException",
|
||||||
|
"Received "
|
||||||
|
+ exception.getClass().getSimpleName()
|
||||||
|
+ " with message: "
|
||||||
|
+ exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionLostWithoutCallback(token, exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyStatusCallbackForSessionClosed(@NonNull Exception exception) {
|
||||||
|
final int errorCode;
|
||||||
|
final String exceptionClass;
|
||||||
|
final String exceptionMessage;
|
||||||
|
|
||||||
|
if (exception instanceof AuthenticationFailedException) {
|
||||||
|
errorCode = VCN_ERROR_CODE_CONFIG_ERROR;
|
||||||
|
exceptionClass = exception.getClass().getName();
|
||||||
|
exceptionMessage = exception.getMessage();
|
||||||
|
} else if (exception instanceof IkeInternalException
|
||||||
|
&& exception.getCause() instanceof IOException) {
|
||||||
|
errorCode = VCN_ERROR_CODE_NETWORK_ERROR;
|
||||||
|
exceptionClass = "java.io.IOException";
|
||||||
|
exceptionMessage = exception.getCause().getMessage();
|
||||||
|
} else {
|
||||||
|
errorCode = VCN_ERROR_CODE_INTERNAL_ERROR;
|
||||||
|
exceptionClass = "java.lang.RuntimeException";
|
||||||
|
exceptionMessage =
|
||||||
|
"Received "
|
||||||
|
+ exception.getClass().getSimpleName()
|
||||||
|
+ " with message: "
|
||||||
|
+ exception.getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
mGatewayStatusCallback.onGatewayConnectionError(
|
||||||
|
mConnectionConfig.getRequiredUnderlyingCapabilities(),
|
||||||
|
errorCode,
|
||||||
|
exceptionClass,
|
||||||
|
exceptionMessage);
|
||||||
|
}
|
||||||
|
|
||||||
private void sessionClosed(int token, @Nullable Exception exception) {
|
private void sessionClosed(int token, @Nullable Exception exception) {
|
||||||
|
if (exception != null) {
|
||||||
|
notifyStatusCallbackForSessionClosed(exception);
|
||||||
|
}
|
||||||
|
|
||||||
// SESSION_LOST MUST be sent before SESSION_CLOSED to ensure that the SM moves to the
|
// SESSION_LOST MUST be sent before SESSION_CLOSED to ensure that the SM moves to the
|
||||||
// Disconnecting state.
|
// Disconnecting state.
|
||||||
sessionLost(token, exception);
|
sessionLostWithoutCallback(token, exception);
|
||||||
sendMessageAndAcquireWakeLock(EVENT_SESSION_CLOSED, token);
|
sendMessageAndAcquireWakeLock(EVENT_SESSION_CLOSED, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1084,6 +1142,8 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void handleDisconnectRequested(String msg) {
|
protected void handleDisconnectRequested(String msg) {
|
||||||
|
// TODO(b/180526152): notify VcnStatusCallback for Network loss
|
||||||
|
|
||||||
Slog.v(TAG, "Tearing down. Cause: " + msg);
|
Slog.v(TAG, "Tearing down. Cause: " + msg);
|
||||||
mIsRunning = false;
|
mIsRunning = false;
|
||||||
|
|
||||||
@@ -1228,6 +1288,8 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
|
|
||||||
String reason = ((EventDisconnectRequestedInfo) msg.obj).reason;
|
String reason = ((EventDisconnectRequestedInfo) msg.obj).reason;
|
||||||
if (reason.equals(DISCONNECT_REASON_UNDERLYING_NETWORK_LOST)) {
|
if (reason.equals(DISCONNECT_REASON_UNDERLYING_NETWORK_LOST)) {
|
||||||
|
// TODO(b/180526152): notify VcnStatusCallback for Network loss
|
||||||
|
|
||||||
// Will trigger EVENT_SESSION_CLOSED immediately.
|
// Will trigger EVENT_SESSION_CLOSED immediately.
|
||||||
mIkeSession.kill();
|
mIkeSession.kill();
|
||||||
break;
|
break;
|
||||||
@@ -1573,8 +1635,7 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void exitState() {
|
protected void exitState() {
|
||||||
// Attempt to set the safe mode alarm - this requires the Vcn Network being validated
|
// Will only set a new alarm if no safe mode alarm is currently scheduled.
|
||||||
// while in ConnectedState (which cancels the previous alarm)
|
|
||||||
setSafeModeAlarm();
|
setSafeModeAlarm();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals;
|
|||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.ArgumentMatchers.notNull;
|
||||||
import static org.mockito.Mockito.any;
|
import static org.mockito.Mockito.any;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
@@ -33,6 +34,7 @@ import android.content.Context;
|
|||||||
import android.net.LinkProperties;
|
import android.net.LinkProperties;
|
||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
import android.net.vcn.VcnManager.VcnStatusCallback;
|
import android.net.vcn.VcnManager.VcnStatusCallback;
|
||||||
|
import android.net.vcn.VcnManager.VcnStatusCallbackBinder;
|
||||||
import android.net.vcn.VcnManager.VcnUnderlyingNetworkPolicyListener;
|
import android.net.vcn.VcnManager.VcnUnderlyingNetworkPolicyListener;
|
||||||
import android.os.ParcelUuid;
|
import android.os.ParcelUuid;
|
||||||
|
|
||||||
@@ -40,11 +42,15 @@ import org.junit.Before;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
|
|
||||||
|
import java.net.UnknownHostException;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
public class VcnManagerTest {
|
public class VcnManagerTest {
|
||||||
private static final ParcelUuid SUB_GROUP = new ParcelUuid(new UUID(0, 0));
|
private static final ParcelUuid SUB_GROUP = new ParcelUuid(new UUID(0, 0));
|
||||||
|
private static final int[] UNDERLYING_NETWORK_CAPABILITIES = {
|
||||||
|
NetworkCapabilities.NET_CAPABILITY_IMS, NetworkCapabilities.NET_CAPABILITY_INTERNET
|
||||||
|
};
|
||||||
private static final Executor INLINE_EXECUTOR = Runnable::run;
|
private static final Executor INLINE_EXECUTOR = Runnable::run;
|
||||||
|
|
||||||
private IVcnManagementService mMockVcnManagementService;
|
private IVcnManagementService mMockVcnManagementService;
|
||||||
@@ -144,14 +150,8 @@ public class VcnManagerTest {
|
|||||||
public void testRegisterVcnStatusCallback() throws Exception {
|
public void testRegisterVcnStatusCallback() throws Exception {
|
||||||
mVcnManager.registerVcnStatusCallback(SUB_GROUP, INLINE_EXECUTOR, mMockStatusCallback);
|
mVcnManager.registerVcnStatusCallback(SUB_GROUP, INLINE_EXECUTOR, mMockStatusCallback);
|
||||||
|
|
||||||
ArgumentCaptor<IVcnStatusCallback> captor =
|
|
||||||
ArgumentCaptor.forClass(IVcnStatusCallback.class);
|
|
||||||
verify(mMockVcnManagementService)
|
verify(mMockVcnManagementService)
|
||||||
.registerVcnStatusCallback(eq(SUB_GROUP), captor.capture(), any());
|
.registerVcnStatusCallback(eq(SUB_GROUP), notNull(), any());
|
||||||
|
|
||||||
IVcnStatusCallback callbackWrapper = captor.getValue();
|
|
||||||
callbackWrapper.onEnteredSafeMode();
|
|
||||||
verify(mMockStatusCallback).onEnteredSafeMode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
@Test(expected = IllegalStateException.class)
|
||||||
@@ -195,4 +195,24 @@ public class VcnManagerTest {
|
|||||||
public void testUnregisterNullVcnStatusCallback() throws Exception {
|
public void testUnregisterNullVcnStatusCallback() throws Exception {
|
||||||
mVcnManager.unregisterVcnStatusCallback(null);
|
mVcnManager.unregisterVcnStatusCallback(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVcnStatusCallbackBinder() throws Exception {
|
||||||
|
IVcnStatusCallback cbBinder =
|
||||||
|
new VcnStatusCallbackBinder(INLINE_EXECUTOR, mMockStatusCallback);
|
||||||
|
|
||||||
|
cbBinder.onEnteredSafeMode();
|
||||||
|
verify(mMockStatusCallback).onEnteredSafeMode();
|
||||||
|
|
||||||
|
cbBinder.onGatewayConnectionError(
|
||||||
|
UNDERLYING_NETWORK_CAPABILITIES,
|
||||||
|
VcnManager.VCN_ERROR_CODE_NETWORK_ERROR,
|
||||||
|
"java.net.UnknownHostException",
|
||||||
|
"exception_message");
|
||||||
|
verify(mMockStatusCallback)
|
||||||
|
.onGatewayConnectionError(
|
||||||
|
eq(UNDERLYING_NETWORK_CAPABILITIES),
|
||||||
|
eq(VcnManager.VCN_ERROR_CODE_NETWORK_ERROR),
|
||||||
|
any(UnknownHostException.class));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ import androidx.test.filters.SmallTest;
|
|||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
import com.android.internal.util.LocationPermissionChecker;
|
import com.android.internal.util.LocationPermissionChecker;
|
||||||
import com.android.server.VcnManagementService.VcnSafeModeCallback;
|
import com.android.server.VcnManagementService.VcnCallback;
|
||||||
import com.android.server.VcnManagementService.VcnStatusCallbackInfo;
|
import com.android.server.VcnManagementService.VcnStatusCallbackInfo;
|
||||||
import com.android.server.vcn.TelephonySubscriptionTracker;
|
import com.android.server.vcn.TelephonySubscriptionTracker;
|
||||||
import com.android.server.vcn.Vcn;
|
import com.android.server.vcn.Vcn;
|
||||||
@@ -156,8 +156,8 @@ public class VcnManagementServiceTest {
|
|||||||
private final LocationPermissionChecker mLocationPermissionChecker =
|
private final LocationPermissionChecker mLocationPermissionChecker =
|
||||||
mock(LocationPermissionChecker.class);
|
mock(LocationPermissionChecker.class);
|
||||||
|
|
||||||
private final ArgumentCaptor<VcnSafeModeCallback> mSafeModeCallbackCaptor =
|
private final ArgumentCaptor<VcnCallback> mVcnCallbackCaptor =
|
||||||
ArgumentCaptor.forClass(VcnSafeModeCallback.class);
|
ArgumentCaptor.forClass(VcnCallback.class);
|
||||||
|
|
||||||
private final VcnManagementService mVcnMgmtSvc;
|
private final VcnManagementService mVcnMgmtSvc;
|
||||||
|
|
||||||
@@ -721,7 +721,7 @@ public class VcnManagementServiceTest {
|
|||||||
verify(mMockPolicyListener).onPolicyChanged();
|
verify(mMockPolicyListener).onPolicyChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyVcnSafeModeCallback(
|
private void verifyVcnCallback(
|
||||||
@NonNull ParcelUuid subGroup, @NonNull TelephonySubscriptionSnapshot snapshot)
|
@NonNull ParcelUuid subGroup, @NonNull TelephonySubscriptionSnapshot snapshot)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
verify(mMockDeps)
|
verify(mMockDeps)
|
||||||
@@ -730,22 +730,22 @@ public class VcnManagementServiceTest {
|
|||||||
eq(subGroup),
|
eq(subGroup),
|
||||||
eq(TEST_VCN_CONFIG),
|
eq(TEST_VCN_CONFIG),
|
||||||
eq(snapshot),
|
eq(snapshot),
|
||||||
mSafeModeCallbackCaptor.capture());
|
mVcnCallbackCaptor.capture());
|
||||||
|
|
||||||
mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
|
mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
|
||||||
|
|
||||||
VcnSafeModeCallback safeModeCallback = mSafeModeCallbackCaptor.getValue();
|
VcnCallback vcnCallback = mVcnCallbackCaptor.getValue();
|
||||||
safeModeCallback.onEnteredSafeMode();
|
vcnCallback.onEnteredSafeMode();
|
||||||
|
|
||||||
verify(mMockPolicyListener).onPolicyChanged();
|
verify(mMockPolicyListener).onPolicyChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testVcnSafeModeCallbackOnEnteredSafeMode() throws Exception {
|
public void testVcnCallbackOnEnteredSafeMode() throws Exception {
|
||||||
TelephonySubscriptionSnapshot snapshot =
|
TelephonySubscriptionSnapshot snapshot =
|
||||||
triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1));
|
triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_1));
|
||||||
|
|
||||||
verifyVcnSafeModeCallback(TEST_UUID_1, snapshot);
|
verifyVcnCallback(TEST_UUID_1, snapshot);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void triggerVcnStatusCallbackOnEnteredSafeMode(
|
private void triggerVcnStatusCallbackOnEnteredSafeMode(
|
||||||
@@ -771,7 +771,7 @@ public class VcnManagementServiceTest {
|
|||||||
// Trigger systemReady() to set up LocationPermissionChecker
|
// Trigger systemReady() to set up LocationPermissionChecker
|
||||||
mVcnMgmtSvc.systemReady();
|
mVcnMgmtSvc.systemReady();
|
||||||
|
|
||||||
verifyVcnSafeModeCallback(subGroup, snapshot);
|
verifyVcnCallback(subGroup, snapshot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ import static android.net.IpSecManager.DIRECTION_IN;
|
|||||||
import static android.net.IpSecManager.DIRECTION_OUT;
|
import static android.net.IpSecManager.DIRECTION_OUT;
|
||||||
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
||||||
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
||||||
|
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_CONFIG_ERROR;
|
||||||
|
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_INTERNAL_ERROR;
|
||||||
|
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_NETWORK_ERROR;
|
||||||
|
|
||||||
import static com.android.server.vcn.VcnGatewayConnection.VcnChildSessionConfiguration;
|
import static com.android.server.vcn.VcnGatewayConnection.VcnChildSessionConfiguration;
|
||||||
import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession;
|
import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession;
|
||||||
@@ -39,6 +42,11 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
|
|||||||
import android.net.LinkProperties;
|
import android.net.LinkProperties;
|
||||||
import android.net.NetworkAgent;
|
import android.net.NetworkAgent;
|
||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
|
import android.net.ipsec.ike.exceptions.AuthenticationFailedException;
|
||||||
|
import android.net.ipsec.ike.exceptions.IkeException;
|
||||||
|
import android.net.ipsec.ike.exceptions.IkeInternalException;
|
||||||
|
import android.net.ipsec.ike.exceptions.TemporaryFailureException;
|
||||||
|
import android.net.vcn.VcnManager.VcnErrorCode;
|
||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
@@ -48,6 +56,8 @@ import org.junit.Test;
|
|||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
/** Tests for VcnGatewayConnection.ConnectedState */
|
/** Tests for VcnGatewayConnection.ConnectedState */
|
||||||
@@ -208,6 +218,25 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
|
|||||||
|
|
||||||
// Since network never validated, verify mSafeModeTimeoutAlarm not canceled
|
// Since network never validated, verify mSafeModeTimeoutAlarm not canceled
|
||||||
verifyNoMoreInteractions(mSafeModeTimeoutAlarm);
|
verifyNoMoreInteractions(mSafeModeTimeoutAlarm);
|
||||||
|
|
||||||
|
// The child session was closed without exception, so verify that the GatewayStatusCallback
|
||||||
|
// was not notified
|
||||||
|
verifyNoMoreInteractions(mGatewayStatusCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChildSessionClosedExceptionallyNotifiesGatewayStatusCallback()
|
||||||
|
throws Exception {
|
||||||
|
final IkeInternalException exception = new IkeInternalException(mock(IOException.class));
|
||||||
|
getChildSessionCallback().onClosedExceptionally(exception);
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
verify(mGatewayStatusCallback)
|
||||||
|
.onGatewayConnectionError(
|
||||||
|
eq(mConfig.getRequiredUnderlyingCapabilities()),
|
||||||
|
eq(VCN_ERROR_CODE_INTERNAL_ERROR),
|
||||||
|
any(),
|
||||||
|
any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -223,5 +252,42 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
|
|||||||
|
|
||||||
// Since network never validated, verify mSafeModeTimeoutAlarm not canceled
|
// Since network never validated, verify mSafeModeTimeoutAlarm not canceled
|
||||||
verifyNoMoreInteractions(mSafeModeTimeoutAlarm);
|
verifyNoMoreInteractions(mSafeModeTimeoutAlarm);
|
||||||
|
|
||||||
|
// IkeSession closed with no error, so verify that the GatewayStatusCallback was not
|
||||||
|
// notified
|
||||||
|
verifyNoMoreInteractions(mGatewayStatusCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyIkeSessionClosedExceptionalltyNotifiesStatusCallback(
|
||||||
|
IkeException cause, @VcnErrorCode int expectedErrorType) {
|
||||||
|
getIkeSessionCallback().onClosedExceptionally(cause);
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
verify(mIkeSession).close();
|
||||||
|
|
||||||
|
verify(mGatewayStatusCallback)
|
||||||
|
.onGatewayConnectionError(
|
||||||
|
eq(mConfig.getRequiredUnderlyingCapabilities()),
|
||||||
|
eq(expectedErrorType),
|
||||||
|
any(),
|
||||||
|
any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIkeSessionClosedExceptionallyAuthenticationFailure() throws Exception {
|
||||||
|
verifyIkeSessionClosedExceptionalltyNotifiesStatusCallback(
|
||||||
|
new AuthenticationFailedException("vcn test"), VCN_ERROR_CODE_CONFIG_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIkeSessionClosedExceptionallyDnsFailure() throws Exception {
|
||||||
|
verifyIkeSessionClosedExceptionalltyNotifiesStatusCallback(
|
||||||
|
new IkeInternalException(new UnknownHostException()), VCN_ERROR_CODE_NETWORK_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIkeSessionClosedExceptionallyInternalFailure() throws Exception {
|
||||||
|
verifyIkeSessionClosedExceptionalltyNotifiesStatusCallback(
|
||||||
|
new TemporaryFailureException("vcn test"), VCN_ERROR_CODE_INTERNAL_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ 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.VcnManagementService.VcnCallback;
|
||||||
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.Vcn.VcnGatewayStatusCallback;
|
||||||
import com.android.server.vcn.VcnNetworkProvider.NetworkRequestListener;
|
import com.android.server.vcn.VcnNetworkProvider.NetworkRequestListener;
|
||||||
@@ -56,7 +56,7 @@ 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 VcnCallback mVcnCallback;
|
||||||
private Vcn.Dependencies mDeps;
|
private Vcn.Dependencies mDeps;
|
||||||
|
|
||||||
private ArgumentCaptor<VcnGatewayStatusCallback> mGatewayStatusCallbackCaptor;
|
private ArgumentCaptor<VcnGatewayStatusCallback> mGatewayStatusCallbackCaptor;
|
||||||
@@ -72,7 +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);
|
mVcnCallback = mock(VcnCallback.class);
|
||||||
mDeps = mock(Vcn.Dependencies.class);
|
mDeps = mock(Vcn.Dependencies.class);
|
||||||
|
|
||||||
mTestLooper = new TestLooper();
|
mTestLooper = new TestLooper();
|
||||||
@@ -104,7 +104,7 @@ public class VcnTest {
|
|||||||
TEST_SUB_GROUP,
|
TEST_SUB_GROUP,
|
||||||
mConfig,
|
mConfig,
|
||||||
mSubscriptionSnapshot,
|
mSubscriptionSnapshot,
|
||||||
mVcnSafeModeCallback,
|
mVcnCallback,
|
||||||
mDeps);
|
mDeps);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,6 +179,6 @@ public class VcnTest {
|
|||||||
verify(gatewayConnection).teardownAsynchronously();
|
verify(gatewayConnection).teardownAsynchronously();
|
||||||
}
|
}
|
||||||
verify(mVcnNetworkProvider).unregisterListener(requestListener);
|
verify(mVcnNetworkProvider).unregisterListener(requestListener);
|
||||||
verify(mVcnSafeModeCallback).onEnteredSafeMode();
|
verify(mVcnCallback).onEnteredSafeMode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user