Merge "Add a retry mechanism when error is recoverable"
This commit is contained in:
@@ -193,11 +193,19 @@ public class Vpn {
|
|||||||
private static final long VPN_LAUNCH_IDLE_ALLOWLIST_DURATION_MS = 60 * 1000;
|
private static final long VPN_LAUNCH_IDLE_ALLOWLIST_DURATION_MS = 60 * 1000;
|
||||||
|
|
||||||
// Length of time (in milliseconds) that an app registered for VpnManager events is placed on
|
// Length of time (in milliseconds) that an app registered for VpnManager events is placed on
|
||||||
// the device idle allowlist each time the a VpnManager event is fired.
|
// the device idle allowlist each time the VpnManager event is fired.
|
||||||
private static final long VPN_MANAGER_EVENT_ALLOWLIST_DURATION_MS = 30 * 1000;
|
private static final long VPN_MANAGER_EVENT_ALLOWLIST_DURATION_MS = 30 * 1000;
|
||||||
|
|
||||||
private static final String LOCKDOWN_ALLOWLIST_SETTING_NAME =
|
private static final String LOCKDOWN_ALLOWLIST_SETTING_NAME =
|
||||||
Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST;
|
Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The retries for consecutive failures.
|
||||||
|
*
|
||||||
|
* <p>If retries have exceeded the length of this array, the last entry in the array will be
|
||||||
|
* used as a repeating interval.
|
||||||
|
*/
|
||||||
|
private static final long[] IKEV2_VPN_RETRY_DELAYS_SEC = {1L, 2L, 5L, 30L, 60L, 300L, 900L};
|
||||||
/**
|
/**
|
||||||
* Largest profile size allowable for Platform VPNs.
|
* Largest profile size allowable for Platform VPNs.
|
||||||
*
|
*
|
||||||
@@ -476,6 +484,20 @@ public class Vpn {
|
|||||||
"Cannot set tunnel's fd as blocking=" + blocking, e);
|
"Cannot set tunnel's fd as blocking=" + blocking, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the next retry delay
|
||||||
|
*
|
||||||
|
* <p>If retries have exceeded the IKEV2_VPN_RETRY_DELAYS_SEC, the last entry in
|
||||||
|
* the array will be used as a repeating interval.
|
||||||
|
*/
|
||||||
|
public long getNextRetryDelaySeconds(int retryCount) {
|
||||||
|
if (retryCount >= IKEV2_VPN_RETRY_DELAYS_SEC.length) {
|
||||||
|
return IKEV2_VPN_RETRY_DELAYS_SEC[IKEV2_VPN_RETRY_DELAYS_SEC.length - 1];
|
||||||
|
} else {
|
||||||
|
return IKEV2_VPN_RETRY_DELAYS_SEC[retryCount];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vpn(Looper looper, Context context, INetworkManagementService netService, INetd netd,
|
public Vpn(Looper looper, Context context, INetworkManagementService netService, INetd netd,
|
||||||
@@ -2667,6 +2689,7 @@ public class Vpn {
|
|||||||
private final ScheduledThreadPoolExecutor mExecutor = new ScheduledThreadPoolExecutor(1);
|
private final ScheduledThreadPoolExecutor mExecutor = new ScheduledThreadPoolExecutor(1);
|
||||||
|
|
||||||
@Nullable private ScheduledFuture<?> mScheduledHandleNetworkLostTimeout;
|
@Nullable private ScheduledFuture<?> mScheduledHandleNetworkLostTimeout;
|
||||||
|
@Nullable private ScheduledFuture<?> mScheduledHandleRetryIkeSessionTimeout;
|
||||||
|
|
||||||
/** Signal to ensure shutdown is honored even if a new Network is connected. */
|
/** Signal to ensure shutdown is honored even if a new Network is connected. */
|
||||||
private boolean mIsRunning = true;
|
private boolean mIsRunning = true;
|
||||||
@@ -2690,6 +2713,14 @@ public class Vpn {
|
|||||||
// mMobikeEnabled can only be updated after IKE AUTH is finished.
|
// mMobikeEnabled can only be updated after IKE AUTH is finished.
|
||||||
private boolean mMobikeEnabled = false;
|
private boolean mMobikeEnabled = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of attempts since the last successful connection.
|
||||||
|
*
|
||||||
|
* <p>This variable controls the retry delay, and is reset when a new IKE session is
|
||||||
|
* opened or when there is a new default network.
|
||||||
|
*/
|
||||||
|
private int mRetryCount = 0;
|
||||||
|
|
||||||
IkeV2VpnRunner(@NonNull Ikev2VpnProfile profile) {
|
IkeV2VpnRunner(@NonNull Ikev2VpnProfile profile) {
|
||||||
super(TAG);
|
super(TAG);
|
||||||
mProfile = profile;
|
mProfile = profile;
|
||||||
@@ -2766,6 +2797,7 @@ public class Vpn {
|
|||||||
ikeConfiguration.isIkeExtensionEnabled(
|
ikeConfiguration.isIkeExtensionEnabled(
|
||||||
IkeSessionConfiguration.EXTENSION_TYPE_MOBIKE);
|
IkeSessionConfiguration.EXTENSION_TYPE_MOBIKE);
|
||||||
onIkeConnectionInfoChanged(token, ikeConfiguration.getIkeSessionConnectionInfo());
|
onIkeConnectionInfoChanged(token, ikeConfiguration.getIkeSessionConnectionInfo());
|
||||||
|
mRetryCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2962,16 +2994,42 @@ public class Vpn {
|
|||||||
public void onDefaultNetworkChanged(@NonNull Network network) {
|
public void onDefaultNetworkChanged(@NonNull Network network) {
|
||||||
Log.d(TAG, "onDefaultNetworkChanged: " + network);
|
Log.d(TAG, "onDefaultNetworkChanged: " + network);
|
||||||
|
|
||||||
|
// If there is a new default network brought up, cancel the retry task to prevent
|
||||||
|
// establishing an unnecessary IKE session.
|
||||||
|
cancelRetryNewIkeSessionFuture();
|
||||||
|
|
||||||
|
// If there is a new default network brought up, cancel the obsolete reset and retry
|
||||||
|
// task.
|
||||||
cancelHandleNetworkLostTimeout();
|
cancelHandleNetworkLostTimeout();
|
||||||
|
|
||||||
|
if (!mIsRunning) {
|
||||||
|
Log.d(TAG, "onDefaultNetworkChanged after exit");
|
||||||
|
return; // VPN has been shut down.
|
||||||
|
}
|
||||||
|
|
||||||
|
mActiveNetwork = network;
|
||||||
|
mRetryCount = 0;
|
||||||
|
|
||||||
|
startOrMigrateIkeSession(network);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start a new IKE session.
|
||||||
|
*
|
||||||
|
* <p>This method MUST always be called on the mExecutor thread in order to ensure
|
||||||
|
* consistency of the Ikev2VpnRunner fields.
|
||||||
|
*
|
||||||
|
* @param underlyingNetwork if the value is {@code null}, which means there is no active
|
||||||
|
* network can be used, do nothing and return immediately. Otherwise, use the
|
||||||
|
* given network to start a new IKE session.
|
||||||
|
*/
|
||||||
|
private void startOrMigrateIkeSession(@Nullable Network underlyingNetwork) {
|
||||||
|
if (underlyingNetwork == null) {
|
||||||
|
Log.d(TAG, "There is no active network for starting an IKE session");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!mIsRunning) {
|
|
||||||
Log.d(TAG, "onDefaultNetworkChanged after exit");
|
|
||||||
return; // VPN has been shut down.
|
|
||||||
}
|
|
||||||
|
|
||||||
mActiveNetwork = network;
|
|
||||||
|
|
||||||
if (mSession != null && mMobikeEnabled) {
|
if (mSession != null && mMobikeEnabled) {
|
||||||
// IKE session can schedule a migration event only when IKE AUTH is finished
|
// IKE session can schedule a migration event only when IKE AUTH is finished
|
||||||
// and mMobikeEnabled is true.
|
// and mMobikeEnabled is true.
|
||||||
@@ -2980,11 +3038,13 @@ public class Vpn {
|
|||||||
"Migrate IKE Session with token "
|
"Migrate IKE Session with token "
|
||||||
+ mCurrentToken
|
+ mCurrentToken
|
||||||
+ " to network "
|
+ " to network "
|
||||||
+ network);
|
+ underlyingNetwork);
|
||||||
mSession.setNetwork(network);
|
mSession.setNetwork(underlyingNetwork);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.d(TAG, "Start new IKE session on network " + underlyingNetwork);
|
||||||
|
|
||||||
// Clear mInterface to prevent Ikev2VpnRunner being cleared when
|
// Clear mInterface to prevent Ikev2VpnRunner being cleared when
|
||||||
// interfaceRemoved() is called.
|
// interfaceRemoved() is called.
|
||||||
mInterface = null;
|
mInterface = null;
|
||||||
@@ -3000,12 +3060,12 @@ public class Vpn {
|
|||||||
final ChildSessionParams childSessionParams;
|
final ChildSessionParams childSessionParams;
|
||||||
if (ikeTunConnParams != null) {
|
if (ikeTunConnParams != null) {
|
||||||
final IkeSessionParams.Builder builder = new IkeSessionParams.Builder(
|
final IkeSessionParams.Builder builder = new IkeSessionParams.Builder(
|
||||||
ikeTunConnParams.getIkeSessionParams()).setNetwork(network);
|
ikeTunConnParams.getIkeSessionParams()).setNetwork(underlyingNetwork);
|
||||||
ikeSessionParams = builder.build();
|
ikeSessionParams = builder.build();
|
||||||
childSessionParams = ikeTunConnParams.getTunnelModeChildSessionParams();
|
childSessionParams = ikeTunConnParams.getTunnelModeChildSessionParams();
|
||||||
} else {
|
} else {
|
||||||
ikeSessionParams = VpnIkev2Utils.buildIkeSessionParams(
|
ikeSessionParams = VpnIkev2Utils.buildIkeSessionParams(
|
||||||
mContext, mProfile, network);
|
mContext, mProfile, underlyingNetwork);
|
||||||
childSessionParams = VpnIkev2Utils.buildChildSessionParams(
|
childSessionParams = VpnIkev2Utils.buildChildSessionParams(
|
||||||
mProfile.getAllowedAlgorithms());
|
mProfile.getAllowedAlgorithms());
|
||||||
}
|
}
|
||||||
@@ -3020,7 +3080,7 @@ public class Vpn {
|
|||||||
// called. Thus it is safe to build a mTunnelIface before IKE setup.
|
// called. Thus it is safe to build a mTunnelIface before IKE setup.
|
||||||
mTunnelIface =
|
mTunnelIface =
|
||||||
mIpSecManager.createIpSecTunnelInterface(
|
mIpSecManager.createIpSecTunnelInterface(
|
||||||
address /* unused */, address /* unused */, network);
|
address /* unused */, address /* unused */, underlyingNetwork);
|
||||||
NetdUtils.setInterfaceUp(mNetd, mTunnelIface.getInterfaceName());
|
NetdUtils.setInterfaceUp(mNetd, mTunnelIface.getInterfaceName());
|
||||||
|
|
||||||
final int token = ++mCurrentToken;
|
final int token = ++mCurrentToken;
|
||||||
@@ -3041,6 +3101,22 @@ public class Vpn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void scheduleRetryNewIkeSession() {
|
||||||
|
final long retryDelay = mDeps.getNextRetryDelaySeconds(mRetryCount++);
|
||||||
|
Log.d(TAG, "Retry new IKE session after " + retryDelay + " seconds.");
|
||||||
|
// If the default network is lost during the retry delay, the mActiveNetwork will be
|
||||||
|
// null, and the new IKE session won't be established until there is a new default
|
||||||
|
// network bringing up.
|
||||||
|
mScheduledHandleRetryIkeSessionTimeout =
|
||||||
|
mExecutor.schedule(() -> {
|
||||||
|
startOrMigrateIkeSession(mActiveNetwork);
|
||||||
|
|
||||||
|
// Reset mScheduledHandleRetryIkeSessionTimeout since it's already run on
|
||||||
|
// executor thread.
|
||||||
|
mScheduledHandleRetryIkeSessionTimeout = null;
|
||||||
|
}, retryDelay, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
/** Called when the NetworkCapabilities of underlying network is changed */
|
/** Called when the NetworkCapabilities of underlying network is changed */
|
||||||
public void onDefaultNetworkCapabilitiesChanged(@NonNull NetworkCapabilities nc) {
|
public void onDefaultNetworkCapabilitiesChanged(@NonNull NetworkCapabilities nc) {
|
||||||
mUnderlyingNetworkCapabilities = nc;
|
mUnderlyingNetworkCapabilities = nc;
|
||||||
@@ -3062,6 +3138,11 @@ public class Vpn {
|
|||||||
* consistency of the Ikev2VpnRunner fields.
|
* consistency of the Ikev2VpnRunner fields.
|
||||||
*/
|
*/
|
||||||
public void onDefaultNetworkLost(@NonNull Network network) {
|
public void onDefaultNetworkLost(@NonNull Network network) {
|
||||||
|
// If the default network is torn down, there is no need to call
|
||||||
|
// startOrMigrateIkeSession() since it will always check if there is an active network
|
||||||
|
// can be used or not.
|
||||||
|
cancelRetryNewIkeSessionFuture();
|
||||||
|
|
||||||
if (!isActiveNetwork(network)) {
|
if (!isActiveNetwork(network)) {
|
||||||
Log.d(TAG, "onDefaultNetworkLost called for obsolete network " + network);
|
Log.d(TAG, "onDefaultNetworkLost called for obsolete network " + network);
|
||||||
|
|
||||||
@@ -3071,6 +3152,8 @@ public class Vpn {
|
|||||||
// or an error was encountered somewhere else). In both cases, all resources and
|
// or an error was encountered somewhere else). In both cases, all resources and
|
||||||
// sessions are torn down via resetIkeState().
|
// sessions are torn down via resetIkeState().
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
mActiveNetwork = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mScheduledHandleNetworkLostTimeout != null
|
if (mScheduledHandleNetworkLostTimeout != null
|
||||||
@@ -3083,7 +3166,7 @@ public class Vpn {
|
|||||||
TAG,
|
TAG,
|
||||||
"Unexpected error in onDefaultNetworkLost. Tear down session",
|
"Unexpected error in onDefaultNetworkLost. Tear down session",
|
||||||
exception);
|
exception);
|
||||||
handleSessionLost(exception);
|
handleSessionLost(exception, network);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3092,7 +3175,7 @@ public class Vpn {
|
|||||||
TAG,
|
TAG,
|
||||||
"IKE Session has mobility. Delay handleSessionLost for losing network "
|
"IKE Session has mobility. Delay handleSessionLost for losing network "
|
||||||
+ network
|
+ network
|
||||||
+ "on session with token "
|
+ " on session with token "
|
||||||
+ mCurrentToken);
|
+ mCurrentToken);
|
||||||
|
|
||||||
// Delay the teardown in case a new network will be available soon. For example,
|
// Delay the teardown in case a new network will be available soon. For example,
|
||||||
@@ -3101,13 +3184,13 @@ public class Vpn {
|
|||||||
mScheduledHandleNetworkLostTimeout =
|
mScheduledHandleNetworkLostTimeout =
|
||||||
mExecutor.schedule(
|
mExecutor.schedule(
|
||||||
() -> {
|
() -> {
|
||||||
handleSessionLost(null);
|
handleSessionLost(null, network);
|
||||||
},
|
},
|
||||||
NETWORK_LOST_TIMEOUT_MS,
|
NETWORK_LOST_TIMEOUT_MS,
|
||||||
TimeUnit.MILLISECONDS);
|
TimeUnit.MILLISECONDS);
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "Call handleSessionLost for losing network " + network);
|
Log.d(TAG, "Call handleSessionLost for losing network " + network);
|
||||||
handleSessionLost(null);
|
handleSessionLost(null, network);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3120,6 +3203,20 @@ public class Vpn {
|
|||||||
// mExecutor who has only one thread.
|
// mExecutor who has only one thread.
|
||||||
Log.d(TAG, "Cancel the task for handling network lost timeout");
|
Log.d(TAG, "Cancel the task for handling network lost timeout");
|
||||||
mScheduledHandleNetworkLostTimeout.cancel(false /* mayInterruptIfRunning */);
|
mScheduledHandleNetworkLostTimeout.cancel(false /* mayInterruptIfRunning */);
|
||||||
|
mScheduledHandleNetworkLostTimeout = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancelRetryNewIkeSessionFuture() {
|
||||||
|
if (mScheduledHandleRetryIkeSessionTimeout != null
|
||||||
|
&& !mScheduledHandleRetryIkeSessionTimeout.isDone()) {
|
||||||
|
// It does not matter what to put in #cancel(boolean), because it is impossible
|
||||||
|
// that the task tracked by mScheduledHandleRetryIkeSessionTimeout is
|
||||||
|
// in-progress since both that task and onDefaultNetworkChanged are submitted to
|
||||||
|
// mExecutor who has only one thread.
|
||||||
|
Log.d(TAG, "Cancel the task for handling new ike session timeout");
|
||||||
|
mScheduledHandleRetryIkeSessionTimeout.cancel(false /* mayInterruptIfRunning */);
|
||||||
|
mScheduledHandleRetryIkeSessionTimeout = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3155,10 +3252,10 @@ public class Vpn {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSessionLost(exception);
|
handleSessionLost(exception, mActiveNetwork);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSessionLost(@Nullable Exception exception) {
|
private void handleSessionLost(@Nullable Exception exception, @Nullable Network network) {
|
||||||
// Cancel mScheduledHandleNetworkLostTimeout if the session it is going to terminate is
|
// Cancel mScheduledHandleNetworkLostTimeout if the session it is going to terminate is
|
||||||
// already terminated due to other failures.
|
// already terminated due to other failures.
|
||||||
cancelHandleNetworkLostTimeout();
|
cancelHandleNetworkLostTimeout();
|
||||||
@@ -3182,7 +3279,7 @@ public class Vpn {
|
|||||||
VpnManager.ERROR_CLASS_NOT_RECOVERABLE,
|
VpnManager.ERROR_CLASS_NOT_RECOVERABLE,
|
||||||
ikeException.getErrorType(),
|
ikeException.getErrorType(),
|
||||||
getPackage(), mSessionKey, makeVpnProfileStateLocked(),
|
getPackage(), mSessionKey, makeVpnProfileStateLocked(),
|
||||||
mActiveNetwork,
|
network,
|
||||||
getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
|
getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
|
||||||
mUnderlyingNetworkCapabilities),
|
mUnderlyingNetworkCapabilities),
|
||||||
getRedactedLinkPropertiesOfUnderlyingNetwork(
|
getRedactedLinkPropertiesOfUnderlyingNetwork(
|
||||||
@@ -3200,7 +3297,7 @@ public class Vpn {
|
|||||||
VpnManager.ERROR_CLASS_RECOVERABLE,
|
VpnManager.ERROR_CLASS_RECOVERABLE,
|
||||||
ikeException.getErrorType(),
|
ikeException.getErrorType(),
|
||||||
getPackage(), mSessionKey, makeVpnProfileStateLocked(),
|
getPackage(), mSessionKey, makeVpnProfileStateLocked(),
|
||||||
mActiveNetwork,
|
network,
|
||||||
getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
|
getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
|
||||||
mUnderlyingNetworkCapabilities),
|
mUnderlyingNetworkCapabilities),
|
||||||
getRedactedLinkPropertiesOfUnderlyingNetwork(
|
getRedactedLinkPropertiesOfUnderlyingNetwork(
|
||||||
@@ -3219,7 +3316,7 @@ public class Vpn {
|
|||||||
VpnManager.ERROR_CLASS_RECOVERABLE,
|
VpnManager.ERROR_CLASS_RECOVERABLE,
|
||||||
VpnManager.ERROR_CODE_NETWORK_LOST,
|
VpnManager.ERROR_CODE_NETWORK_LOST,
|
||||||
getPackage(), mSessionKey, makeVpnProfileStateLocked(),
|
getPackage(), mSessionKey, makeVpnProfileStateLocked(),
|
||||||
mActiveNetwork,
|
network,
|
||||||
getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
|
getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
|
||||||
mUnderlyingNetworkCapabilities),
|
mUnderlyingNetworkCapabilities),
|
||||||
getRedactedLinkPropertiesOfUnderlyingNetwork(
|
getRedactedLinkPropertiesOfUnderlyingNetwork(
|
||||||
@@ -3234,7 +3331,7 @@ public class Vpn {
|
|||||||
VpnManager.ERROR_CLASS_RECOVERABLE,
|
VpnManager.ERROR_CLASS_RECOVERABLE,
|
||||||
VpnManager.ERROR_CODE_NETWORK_UNKNOWN_HOST,
|
VpnManager.ERROR_CODE_NETWORK_UNKNOWN_HOST,
|
||||||
getPackage(), mSessionKey, makeVpnProfileStateLocked(),
|
getPackage(), mSessionKey, makeVpnProfileStateLocked(),
|
||||||
mActiveNetwork,
|
network,
|
||||||
getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
|
getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
|
||||||
mUnderlyingNetworkCapabilities),
|
mUnderlyingNetworkCapabilities),
|
||||||
getRedactedLinkPropertiesOfUnderlyingNetwork(
|
getRedactedLinkPropertiesOfUnderlyingNetwork(
|
||||||
@@ -3248,7 +3345,7 @@ public class Vpn {
|
|||||||
VpnManager.ERROR_CLASS_RECOVERABLE,
|
VpnManager.ERROR_CLASS_RECOVERABLE,
|
||||||
VpnManager.ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT,
|
VpnManager.ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT,
|
||||||
getPackage(), mSessionKey, makeVpnProfileStateLocked(),
|
getPackage(), mSessionKey, makeVpnProfileStateLocked(),
|
||||||
mActiveNetwork,
|
network,
|
||||||
getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
|
getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
|
||||||
mUnderlyingNetworkCapabilities),
|
mUnderlyingNetworkCapabilities),
|
||||||
getRedactedLinkPropertiesOfUnderlyingNetwork(
|
getRedactedLinkPropertiesOfUnderlyingNetwork(
|
||||||
@@ -3262,7 +3359,7 @@ public class Vpn {
|
|||||||
VpnManager.ERROR_CLASS_RECOVERABLE,
|
VpnManager.ERROR_CLASS_RECOVERABLE,
|
||||||
VpnManager.ERROR_CODE_NETWORK_IO,
|
VpnManager.ERROR_CODE_NETWORK_IO,
|
||||||
getPackage(), mSessionKey, makeVpnProfileStateLocked(),
|
getPackage(), mSessionKey, makeVpnProfileStateLocked(),
|
||||||
mActiveNetwork,
|
network,
|
||||||
getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
|
getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
|
||||||
mUnderlyingNetworkCapabilities),
|
mUnderlyingNetworkCapabilities),
|
||||||
getRedactedLinkPropertiesOfUnderlyingNetwork(
|
getRedactedLinkPropertiesOfUnderlyingNetwork(
|
||||||
@@ -3272,9 +3369,10 @@ public class Vpn {
|
|||||||
} else if (exception != null) {
|
} else if (exception != null) {
|
||||||
Log.wtf(TAG, "onSessionLost: exception = " + exception);
|
Log.wtf(TAG, "onSessionLost: exception = " + exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scheduleRetryNewIkeSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
mActiveNetwork = null;
|
|
||||||
mUnderlyingNetworkCapabilities = null;
|
mUnderlyingNetworkCapabilities = null;
|
||||||
mUnderlyingLinkProperties = null;
|
mUnderlyingLinkProperties = null;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user