Loading src/java/com/android/internal/telephony/data/DataNetworkController.java +5 −2 Original line number Diff line number Diff line Loading @@ -2370,9 +2370,12 @@ public class DataNetworkController extends Handler { + dataSetupRetryEntry + ", allowed reason=" + allowedReason + ", service state=" + mServiceState); for (DataNetwork dataNetwork : mDataNetworkList) { if (dataNetwork.getDataProfile().equals(dataProfile)) { DataProfile currentDataProfile = dataNetwork.getDataProfile(); if (dataProfile.equals(currentDataProfile) || mDataProfileManager.areDataProfilesSharingApn( dataProfile, currentDataProfile)) { log("onSetupDataNetwork: Found existing data network " + dataNetwork + " has the same data profile."); + " using the same or a similar data profile."); if (dataSetupRetryEntry != null) { dataSetupRetryEntry.setState(DataRetryEntry.RETRY_STATE_CANCELLED); } Loading src/java/com/android/internal/telephony/data/DataProfileManager.java +9 −4 Original line number Diff line number Diff line Loading @@ -498,7 +498,7 @@ public class DataProfileManager extends Handler { setPreferredDataProfile(preferredDataProfile); } else { preferredDataProfile = mAllDataProfiles.stream() .filter(dp -> areDataProfileSharingApn(dp, mPreferredDataProfile)) .filter(dp -> areDataProfilesSharingApn(dp, mPreferredDataProfile)) .findFirst() .orElse(null); if (preferredDataProfile != null) { Loading Loading @@ -731,7 +731,7 @@ public class DataProfileManager extends Handler { * @return {@code true} if the data profile is essentially the preferred data profile. */ public boolean isDataProfilePreferred(@NonNull DataProfile dataProfile) { return areDataProfileSharingApn(dataProfile, mPreferredDataProfile); return areDataProfilesSharingApn(dataProfile, mPreferredDataProfile); } /** Loading Loading @@ -965,14 +965,19 @@ public class DataProfileManager extends Handler { // Only check the APN from the profile is compatible or not. return mAllDataProfiles.stream() .anyMatch(dp -> areDataProfileSharingApn(dataProfile, dp)); .filter(dp -> dp.getApnSetting() != null && (dp.getApnSetting().getApnSetId() == Telephony.Carriers.MATCH_ALL_APN_SET_ID || dp.getApnSetting().getApnSetId() == mPreferredDataProfileSetId)) .anyMatch(dp -> areDataProfilesSharingApn(dataProfile, dp)); } /** * @return {@code true} if both data profiles' APN setting are non-null and essentially the same * (non-essential elements include e.g.APN Id). */ private boolean areDataProfileSharingApn(@Nullable DataProfile a, @Nullable DataProfile b) { public boolean areDataProfilesSharingApn(@Nullable DataProfile a, @Nullable DataProfile b) { return a != null && b != null && a.getApnSetting() != null Loading tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java +110 −0 Original line number Diff line number Diff line Loading @@ -194,6 +194,36 @@ public class DataNetworkControllerTest extends TelephonyTest { .setPreferred(false) .build(); // The same data profile but with different auto generated ID, should be considered the same as // mGeneralPurposeDataProfile private final DataProfile mDuplicatedGeneralPurposeDataProfile = new DataProfile.Builder() .setApnSetting(new ApnSetting.Builder() .setId(3612) .setOperatorNumeric("12345") .setEntryName("internet_supl_mms_apn") .setApnName("internet_supl_mms_apn") .setUser("user") .setPassword("passwd") .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_SUPL | ApnSetting.TYPE_MMS) .setProtocol(ApnSetting.PROTOCOL_IPV6) .setRoamingProtocol(ApnSetting.PROTOCOL_IP) .setCarrierEnabled(true) .setNetworkTypeBitmask((int) (TelephonyManager.NETWORK_TYPE_BITMASK_LTE | TelephonyManager.NETWORK_TYPE_BITMASK_IWLAN | TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT)) .setLingeringNetworkTypeBitmask((int) (TelephonyManager.NETWORK_TYPE_BITMASK_LTE | TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT | TelephonyManager.NETWORK_TYPE_BITMASK_UMTS | TelephonyManager.NETWORK_TYPE_BITMASK_NR)) .setProfileId(1234) .setMaxConns(321) .setWaitTime(456) .setMaxConnsTime(789) .build()) .setPreferred(false) .build(); private final DataProfile mImsCellularDataProfile = new DataProfile.Builder() .setApnSetting(new ApnSetting.Builder() .setId(2164) Loading Loading @@ -781,6 +811,17 @@ public class DataNetworkControllerTest extends TelephonyTest { return null; }).when(mDataProfileManager).isDataProfileCompatible(any(DataProfile.class)); doAnswer(invocation -> { DataProfile a = (DataProfile) invocation.getArguments()[0]; DataProfile b = (DataProfile) invocation.getArguments()[1]; return a != null && b != null && a.getApnSetting() != null && a.getApnSetting().equals(b.getApnSetting(), mPhone.getServiceState().getDataRoamingFromRegistration()); }).when(mDataProfileManager).areDataProfilesSharingApn(any(DataProfile.class), any(DataProfile.class)); doAnswer(invocation -> { TelephonyNetworkRequest networkRequest = (TelephonyNetworkRequest) invocation.getArguments()[0]; Loading Loading @@ -1032,6 +1073,75 @@ public class DataNetworkControllerTest extends TelephonyTest { verify(mMockedDataNetworkControllerCallback).onInternetDataNetworkConnected(any()); } @Test public void testSetupDataNetworkWithSimilarDataProfile() throws Exception { mDataNetworkControllerUT.addNetworkRequest( createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET)); processAllMessages(); verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_INTERNET); verifyConnectedNetworkHasDataProfile(mGeneralPurposeDataProfile); List<DataNetwork> dataNetworkList = getDataNetworks(); assertThat(dataNetworkList).hasSize(1); DataNetwork dataNetwork = dataNetworkList.get(0); assertThat(dataNetworkList.get(0).getLinkProperties().getAddresses()).containsExactly( InetAddresses.parseNumericAddress(IPV4_ADDRESS), InetAddresses.parseNumericAddress(IPV6_ADDRESS)); verify(mMockedDataNetworkControllerCallback).onInternetDataNetworkConnected(any()); // database updated/reloaded, causing data profile id change List<DataProfile> profiles = List.of(mDuplicatedGeneralPurposeDataProfile); doAnswer(invocation -> { DataProfile dp = (DataProfile) invocation.getArguments()[0]; if (dp.getApnSetting() == null) return true; for (DataProfile dataProfile : profiles) { if (dataProfile.getApnSetting() != null && dataProfile.getApnSetting().equals(dp.getApnSetting(), false)) { return true; } } return null; }).when(mDataProfileManager).isDataProfileCompatible(any(DataProfile.class)); doAnswer(invocation -> { TelephonyNetworkRequest networkRequest = (TelephonyNetworkRequest) invocation.getArguments()[0]; int networkType = (int) invocation.getArguments()[1]; for (DataProfile dataProfile : profiles) { if (dataProfile.canSatisfy(networkRequest.getCapabilities()) && (dataProfile.getApnSetting().getNetworkTypeBitmask() == 0 || (dataProfile.getApnSetting().getNetworkTypeBitmask() & ServiceState.getBitmaskForTech(networkType)) != 0)) { return dataProfile; } } logd("Cannot find data profile to satisfy " + networkRequest + ", network type=" + TelephonyManager.getNetworkTypeName(networkType)); return null; }).when(mDataProfileManager).getDataProfileForNetworkRequest( any(TelephonyNetworkRequest.class), anyInt()); // verify the network still connects verify(mMockedDataNetworkControllerCallback).onInternetDataNetworkConnected(any()); // A NOT_VCN_MANAGED request cannot be satisfied by the existing network, but will adopt the // same data profile mDataNetworkControllerUT.addNetworkRequest( createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET, NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)); processAllMessages(); // verify the network still connects verify(mMockedDataNetworkControllerCallback).onInternetDataNetworkConnected(any()); // verify we don't try to setup a separate network for the not_vcn_managed request dataNetworkList = getDataNetworks(); assertThat(dataNetworkList).hasSize(1); } @Test public void testSetupImsDataNetwork() throws Exception { mDataNetworkControllerUT.addNetworkRequest( Loading Loading
src/java/com/android/internal/telephony/data/DataNetworkController.java +5 −2 Original line number Diff line number Diff line Loading @@ -2370,9 +2370,12 @@ public class DataNetworkController extends Handler { + dataSetupRetryEntry + ", allowed reason=" + allowedReason + ", service state=" + mServiceState); for (DataNetwork dataNetwork : mDataNetworkList) { if (dataNetwork.getDataProfile().equals(dataProfile)) { DataProfile currentDataProfile = dataNetwork.getDataProfile(); if (dataProfile.equals(currentDataProfile) || mDataProfileManager.areDataProfilesSharingApn( dataProfile, currentDataProfile)) { log("onSetupDataNetwork: Found existing data network " + dataNetwork + " has the same data profile."); + " using the same or a similar data profile."); if (dataSetupRetryEntry != null) { dataSetupRetryEntry.setState(DataRetryEntry.RETRY_STATE_CANCELLED); } Loading
src/java/com/android/internal/telephony/data/DataProfileManager.java +9 −4 Original line number Diff line number Diff line Loading @@ -498,7 +498,7 @@ public class DataProfileManager extends Handler { setPreferredDataProfile(preferredDataProfile); } else { preferredDataProfile = mAllDataProfiles.stream() .filter(dp -> areDataProfileSharingApn(dp, mPreferredDataProfile)) .filter(dp -> areDataProfilesSharingApn(dp, mPreferredDataProfile)) .findFirst() .orElse(null); if (preferredDataProfile != null) { Loading Loading @@ -731,7 +731,7 @@ public class DataProfileManager extends Handler { * @return {@code true} if the data profile is essentially the preferred data profile. */ public boolean isDataProfilePreferred(@NonNull DataProfile dataProfile) { return areDataProfileSharingApn(dataProfile, mPreferredDataProfile); return areDataProfilesSharingApn(dataProfile, mPreferredDataProfile); } /** Loading Loading @@ -965,14 +965,19 @@ public class DataProfileManager extends Handler { // Only check the APN from the profile is compatible or not. return mAllDataProfiles.stream() .anyMatch(dp -> areDataProfileSharingApn(dataProfile, dp)); .filter(dp -> dp.getApnSetting() != null && (dp.getApnSetting().getApnSetId() == Telephony.Carriers.MATCH_ALL_APN_SET_ID || dp.getApnSetting().getApnSetId() == mPreferredDataProfileSetId)) .anyMatch(dp -> areDataProfilesSharingApn(dataProfile, dp)); } /** * @return {@code true} if both data profiles' APN setting are non-null and essentially the same * (non-essential elements include e.g.APN Id). */ private boolean areDataProfileSharingApn(@Nullable DataProfile a, @Nullable DataProfile b) { public boolean areDataProfilesSharingApn(@Nullable DataProfile a, @Nullable DataProfile b) { return a != null && b != null && a.getApnSetting() != null Loading
tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java +110 −0 Original line number Diff line number Diff line Loading @@ -194,6 +194,36 @@ public class DataNetworkControllerTest extends TelephonyTest { .setPreferred(false) .build(); // The same data profile but with different auto generated ID, should be considered the same as // mGeneralPurposeDataProfile private final DataProfile mDuplicatedGeneralPurposeDataProfile = new DataProfile.Builder() .setApnSetting(new ApnSetting.Builder() .setId(3612) .setOperatorNumeric("12345") .setEntryName("internet_supl_mms_apn") .setApnName("internet_supl_mms_apn") .setUser("user") .setPassword("passwd") .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_SUPL | ApnSetting.TYPE_MMS) .setProtocol(ApnSetting.PROTOCOL_IPV6) .setRoamingProtocol(ApnSetting.PROTOCOL_IP) .setCarrierEnabled(true) .setNetworkTypeBitmask((int) (TelephonyManager.NETWORK_TYPE_BITMASK_LTE | TelephonyManager.NETWORK_TYPE_BITMASK_IWLAN | TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT)) .setLingeringNetworkTypeBitmask((int) (TelephonyManager.NETWORK_TYPE_BITMASK_LTE | TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT | TelephonyManager.NETWORK_TYPE_BITMASK_UMTS | TelephonyManager.NETWORK_TYPE_BITMASK_NR)) .setProfileId(1234) .setMaxConns(321) .setWaitTime(456) .setMaxConnsTime(789) .build()) .setPreferred(false) .build(); private final DataProfile mImsCellularDataProfile = new DataProfile.Builder() .setApnSetting(new ApnSetting.Builder() .setId(2164) Loading Loading @@ -781,6 +811,17 @@ public class DataNetworkControllerTest extends TelephonyTest { return null; }).when(mDataProfileManager).isDataProfileCompatible(any(DataProfile.class)); doAnswer(invocation -> { DataProfile a = (DataProfile) invocation.getArguments()[0]; DataProfile b = (DataProfile) invocation.getArguments()[1]; return a != null && b != null && a.getApnSetting() != null && a.getApnSetting().equals(b.getApnSetting(), mPhone.getServiceState().getDataRoamingFromRegistration()); }).when(mDataProfileManager).areDataProfilesSharingApn(any(DataProfile.class), any(DataProfile.class)); doAnswer(invocation -> { TelephonyNetworkRequest networkRequest = (TelephonyNetworkRequest) invocation.getArguments()[0]; Loading Loading @@ -1032,6 +1073,75 @@ public class DataNetworkControllerTest extends TelephonyTest { verify(mMockedDataNetworkControllerCallback).onInternetDataNetworkConnected(any()); } @Test public void testSetupDataNetworkWithSimilarDataProfile() throws Exception { mDataNetworkControllerUT.addNetworkRequest( createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET)); processAllMessages(); verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_INTERNET); verifyConnectedNetworkHasDataProfile(mGeneralPurposeDataProfile); List<DataNetwork> dataNetworkList = getDataNetworks(); assertThat(dataNetworkList).hasSize(1); DataNetwork dataNetwork = dataNetworkList.get(0); assertThat(dataNetworkList.get(0).getLinkProperties().getAddresses()).containsExactly( InetAddresses.parseNumericAddress(IPV4_ADDRESS), InetAddresses.parseNumericAddress(IPV6_ADDRESS)); verify(mMockedDataNetworkControllerCallback).onInternetDataNetworkConnected(any()); // database updated/reloaded, causing data profile id change List<DataProfile> profiles = List.of(mDuplicatedGeneralPurposeDataProfile); doAnswer(invocation -> { DataProfile dp = (DataProfile) invocation.getArguments()[0]; if (dp.getApnSetting() == null) return true; for (DataProfile dataProfile : profiles) { if (dataProfile.getApnSetting() != null && dataProfile.getApnSetting().equals(dp.getApnSetting(), false)) { return true; } } return null; }).when(mDataProfileManager).isDataProfileCompatible(any(DataProfile.class)); doAnswer(invocation -> { TelephonyNetworkRequest networkRequest = (TelephonyNetworkRequest) invocation.getArguments()[0]; int networkType = (int) invocation.getArguments()[1]; for (DataProfile dataProfile : profiles) { if (dataProfile.canSatisfy(networkRequest.getCapabilities()) && (dataProfile.getApnSetting().getNetworkTypeBitmask() == 0 || (dataProfile.getApnSetting().getNetworkTypeBitmask() & ServiceState.getBitmaskForTech(networkType)) != 0)) { return dataProfile; } } logd("Cannot find data profile to satisfy " + networkRequest + ", network type=" + TelephonyManager.getNetworkTypeName(networkType)); return null; }).when(mDataProfileManager).getDataProfileForNetworkRequest( any(TelephonyNetworkRequest.class), anyInt()); // verify the network still connects verify(mMockedDataNetworkControllerCallback).onInternetDataNetworkConnected(any()); // A NOT_VCN_MANAGED request cannot be satisfied by the existing network, but will adopt the // same data profile mDataNetworkControllerUT.addNetworkRequest( createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET, NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)); processAllMessages(); // verify the network still connects verify(mMockedDataNetworkControllerCallback).onInternetDataNetworkConnected(any()); // verify we don't try to setup a separate network for the not_vcn_managed request dataNetworkList = getDataNetworks(); assertThat(dataNetworkList).hasSize(1); } @Test public void testSetupImsDataNetwork() throws Exception { mDataNetworkControllerUT.addNetworkRequest( Loading