Merge changes from topics "kpFromCarrier", "noNetCapNoMigration"

* changes:
  Prevent migrating the session from using the wrong value
  Read NAT keepalive value from carrier config
This commit is contained in:
Chiachang Wang
2023-03-09 12:17:21 +00:00
committed by Gerrit Code Review

View File

@@ -21,6 +21,7 @@ import static android.Manifest.permission.CONTROL_VPN;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.RouteInfo.RTN_THROW;
import static android.net.RouteInfo.RTN_UNREACHABLE;
@@ -29,6 +30,7 @@ import static android.net.ipsec.ike.IkeSessionParams.ESP_ENCAP_TYPE_AUTO;
import static android.net.ipsec.ike.IkeSessionParams.ESP_IP_VERSION_AUTO;
import static android.os.PowerWhitelistManager.REASON_VPN;
import static android.os.UserHandle.PER_USER_RANGE;
import static android.telephony.CarrierConfigManager.KEY_MIN_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT;
import static com.android.net.module.util.NetworkStackConstants.IPV6_MIN_MTU;
import static com.android.server.vcn.util.PersistableBundleUtils.STRING_DESERIALIZER;
@@ -79,7 +81,9 @@ import android.net.NetworkInfo.DetailedState;
import android.net.NetworkProvider;
import android.net.NetworkRequest;
import android.net.NetworkScore;
import android.net.NetworkSpecifier;
import android.net.RouteInfo;
import android.net.TelephonyNetworkSpecifier;
import android.net.UidRangeParcel;
import android.net.UnderlyingNetworkInfo;
import android.net.Uri;
@@ -127,12 +131,16 @@ import android.security.keystore.KeyProperties;
import android.system.keystore2.Domain;
import android.system.keystore2.KeyDescriptor;
import android.system.keystore2.KeyPermission;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
import android.util.LocalLog;
import android.util.Log;
import android.util.Range;
import android.util.SparseArray;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
@@ -268,6 +276,10 @@ public class Vpn {
private final ConnectivityManager mConnectivityManager;
private final AppOpsManager mAppOpsManager;
private final ConnectivityDiagnosticsManager mConnectivityDiagnosticsManager;
private final TelephonyManager mTelephonyManager;
private final CarrierConfigManager mCarrierConfigManager;
private final SubscriptionManager mSubscriptionManager;
// The context is for specific user which is created from mUserId
private final Context mUserIdContext;
@VisibleForTesting final Dependencies mDeps;
@@ -313,6 +325,14 @@ public class Vpn {
private final LocalLog mUnderlyNetworkChanges = new LocalLog(MAX_EVENTS_LOGS);
private final LocalLog mVpnManagerEvents = new LocalLog(MAX_EVENTS_LOGS);
/**
* Cached Map of <subscription ID, keepalive delay ms> since retrieving the PersistableBundle
* and the target value from CarrierConfigManager is somewhat expensive as it has hundreds of
* fields. This cache is cleared when the carrier config changes to ensure data freshness.
*/
@GuardedBy("this")
private final SparseArray<Integer> mCachedKeepalivePerSubId = new SparseArray<>();
/**
* Whether to keep the connection active after rebooting, or upgrading or reinstalling. This
* only applies to {@link VpnService} connections.
@@ -626,6 +646,10 @@ public class Vpn {
mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */);
mConnectivityDiagnosticsManager =
mContext.getSystemService(ConnectivityDiagnosticsManager.class);
mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
mDeps = deps;
mNms = netService;
mNetd = netd;
@@ -2893,6 +2917,24 @@ public class Vpn {
*/
private int mRetryCount = 0;
private CarrierConfigManager.CarrierConfigChangeListener mCarrierConfigChangeListener =
new CarrierConfigManager.CarrierConfigChangeListener() {
@Override
public void onCarrierConfigChanged(int slotIndex, int subId, int carrierId,
int specificCarrierId) {
synchronized (Vpn.this) {
mCachedKeepalivePerSubId.remove(subId);
// Ignore stale runner.
if (mVpnRunner != Vpn.IkeV2VpnRunner.this) return;
maybeMigrateIkeSession(mActiveNetwork);
}
// TODO: update the longLivedTcpConnectionsExpensive value in the
// networkcapabilities of the VPN network.
}
};
IkeV2VpnRunner(
@NonNull Ikev2VpnProfile profile, @NonNull ScheduledThreadPoolExecutor executor) {
super(TAG);
@@ -2918,6 +2960,9 @@ public class Vpn {
setVpnNetworkPreference(mSessionKey,
createUserAndRestrictedProfilesRanges(mUserId,
mConfig.allowedApplications, mConfig.disallowedApplications));
mCarrierConfigManager.registerCarrierConfigChangeListener(mExecutor,
mCarrierConfigChangeListener);
}
@Override
@@ -3257,8 +3302,6 @@ public class Vpn {
mUnderlyingLinkProperties = null;
mUnderlyingNetworkCapabilities = null;
mRetryCount = 0;
startOrMigrateIkeSession(network);
}
@NonNull
@@ -3356,9 +3399,36 @@ public class Vpn {
}
private int guessNattKeepaliveTimerForNetwork() {
// TODO : guess the keepalive delay based on carrier if auto keepalive timer is
// enabled
return AUTOMATIC_KEEPALIVE_DELAY_SECONDS;
final int subId = getCellSubIdForNetworkCapabilities(mUnderlyingNetworkCapabilities);
if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
Log.d(TAG, "Underlying network is not a cellular network");
return AUTOMATIC_KEEPALIVE_DELAY_SECONDS;
}
synchronized (Vpn.this) {
if (mCachedKeepalivePerSubId.contains(subId)) {
Log.d(TAG, "Get cached keepalive config");
return mCachedKeepalivePerSubId.get(subId);
}
final TelephonyManager perSubTm = mTelephonyManager.createForSubscriptionId(subId);
if (perSubTm.getSimApplicationState() != TelephonyManager.SIM_STATE_LOADED) {
Log.d(TAG, "SIM card is not ready on sub " + subId);
return AUTOMATIC_KEEPALIVE_DELAY_SECONDS;
}
final PersistableBundle carrierConfig =
mCarrierConfigManager.getConfigForSubId(subId);
if (!CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfig)) {
return AUTOMATIC_KEEPALIVE_DELAY_SECONDS;
}
final int natKeepalive =
carrierConfig.getInt(KEY_MIN_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT);
mCachedKeepalivePerSubId.put(subId, natKeepalive);
Log.d(TAG, "Get customized keepalive=" + natKeepalive);
return natKeepalive;
}
}
boolean maybeMigrateIkeSession(@NonNull Network underlyingNetwork) {
@@ -3456,7 +3526,15 @@ public class Vpn {
/** Called when the NetworkCapabilities of underlying network is changed */
public void onDefaultNetworkCapabilitiesChanged(@NonNull NetworkCapabilities nc) {
final NetworkCapabilities oldNc = mUnderlyingNetworkCapabilities;
mUnderlyingNetworkCapabilities = nc;
if (oldNc == null) {
// A new default network is available.
startOrMigrateIkeSession(mActiveNetwork);
} else if (!nc.getSubscriptionIds().equals(oldNc.getSubscriptionIds())) {
// Renew carrierConfig values.
maybeMigrateIkeSession(mActiveNetwork);
}
}
/** Called when the LinkProperties of underlying network is changed */
@@ -3812,6 +3890,8 @@ public class Vpn {
resetIkeState();
mCarrierConfigManager.unregisterCarrierConfigChangeListener(
mCarrierConfigChangeListener);
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
mConnectivityDiagnosticsManager.unregisterConnectivityDiagnosticsCallback(
mDiagnosticsCallback);
@@ -4804,6 +4884,8 @@ public class Vpn {
pw.println("Reset session scheduled");
}
}
pw.println("mCachedKeepalivePerSubId=" + mCachedKeepalivePerSubId);
pw.println("mUnderlyNetworkChanges (most recent first):");
pw.increaseIndent();
mUnderlyNetworkChanges.reverseDump(pw);
@@ -4815,4 +4897,19 @@ public class Vpn {
pw.decreaseIndent();
}
}
private static int getCellSubIdForNetworkCapabilities(@Nullable NetworkCapabilities nc) {
if (nc == null) return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
if (!nc.hasTransport(TRANSPORT_CELLULAR)) {
return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
final NetworkSpecifier specifier = nc.getNetworkSpecifier();
if (specifier instanceof TelephonyNetworkSpecifier) {
return ((TelephonyNetworkSpecifier) specifier).getSubscriptionId();
}
return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
}