Loading src/java/com/android/internal/telephony/data/DataNetworkController.java +4 −7 Original line number Diff line number Diff line Loading @@ -1743,13 +1743,10 @@ public class DataNetworkController extends Handler { evaluation.addDataDisallowedReason(DataDisallowedReason.DATA_DISABLED); } // Check if the data profile is still valid, sometimes the users can remove it from the APN // editor. We use very loose check here because APN id can change after APN reset to // default if (mDataProfileManager.getDataProfile( dataProfile.getApnSetting() != null ? dataProfile.getApnSetting().getApnName() : null, dataProfile.getTrafficDescriptor()) == null) { // Check if the data profile is still compatible, sometimes the users can remove it from the // APN editor. If some of the important fields are changed in APN settings, we need to // tear down the network. Note traffic descriptor from the data profile will not be checked. if (!mDataProfileManager.isDataProfileCompatible(dataProfile)) { evaluation.addDataDisallowedReason(DataDisallowedReason.DATA_PROFILE_INVALID); } Loading src/java/com/android/internal/telephony/data/DataProfileManager.java +22 −28 Original line number Diff line number Diff line Loading @@ -86,7 +86,11 @@ public class DataProfileManager extends Handler { /** Cellular data service. */ private final @NonNull DataServiceManager mWwanDataServiceManager; /** All data profiles for the current carrier. */ /** * All data profiles for the current carrier. Note only data profiles loaded from the APN * database will be stored here. The on-demand data profiles (generated dynamically, for * example, enterprise data profiles with differentiator) are not stored here. */ private final @NonNull List<DataProfile> mAllDataProfiles = new ArrayList<>(); /** The data profile used for initial attach. */ Loading Loading @@ -911,39 +915,29 @@ public class DataProfileManager extends Handler { } /** * Get data profile by APN name and/or traffic descriptor. * * @param apnName APN name. * @param trafficDescriptor Traffic descriptor. * Check if the provided data profile is still compatible with the current environment. Note * this method ignores APN id check and traffic descriptor check. A data profile with traffic * descriptor only can always be used in any condition. * * @return Data profile by APN name and/or traffic descriptor. Either one of APN name or * traffic descriptor should be provided. {@code null} if data profile is not found. * @param dataProfile The data profile to check. * @return {@code true} if the provided data profile can be still used in current environment. */ public @Nullable DataProfile getDataProfile(@Nullable String apnName, @Nullable TrafficDescriptor trafficDescriptor) { if (apnName == null && trafficDescriptor == null) return null; List<DataProfile> dataProfiles = mAllDataProfiles; // Check if any existing data profile has the same traffic descriptor. if (trafficDescriptor != null) { dataProfiles = mAllDataProfiles.stream() .filter(dp -> trafficDescriptor.equals(dp.getTrafficDescriptor())) .collect(Collectors.toList()); public boolean isDataProfileCompatible(@NonNull DataProfile dataProfile) { if (dataProfile == null) { return false; } // Check if any existing data profile has the same APN name. if (apnName != null) { dataProfiles = dataProfiles.stream() .filter(dp -> dp.getApnSetting() != null && (dp.getApnSetting().getApnSetId() == Telephony.Carriers.MATCH_ALL_APN_SET_ID || dp.getApnSetting().getApnSetId() == mPreferredDataProfileSetId)) .filter(dp -> apnName.equals(dp.getApnSetting().getApnName())) .collect(Collectors.toList()); if (dataProfile.getApnSetting() == null && dataProfile.getTrafficDescriptor() != null) { // A traffic descriptor only data profile can be always used. Traffic descriptors are // always generated on the fly instead loaded from the database. return true; } return dataProfiles.isEmpty() ? null : dataProfiles.get(0); // Only check the APN from the profile is compatible or not. return mAllDataProfiles.stream() .filter(dp -> dp.getApnSetting() != null) .anyMatch(dp -> dp.getApnSetting().equals(dataProfile.getApnSetting(), mPhone.getServiceState().getDataRoamingFromRegistration())); } /** Loading src/java/com/android/internal/telephony/data/DataRetryManager.java +13 −11 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ import java.util.UUID; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.Stream; /** * DataRetryManager manages data network setup retry and its configurations. Loading Loading @@ -1397,18 +1398,19 @@ public class DataRetryManager extends Handler { // equal to the data profiles kept in data profile manager (due to some fields missing // in DataProfileInfo.aidl), so we need to get the equivalent data profile from data // profile manager. final DataProfile dp = mDataProfileManager.getDataProfile( dataProfile.getApnSetting() != null ? dataProfile.getApnSetting().getApnName() : null, dataProfile.getTrafficDescriptor()); log("onDataProfileUnthrottled: getDataProfile=" + dp); if (dp != null) { dataUnthrottlingEntries = mDataThrottlingEntries.stream() .filter(entry -> entry.expirationTimeMillis > now && entry.dataProfile.equals(dp) && entry.transport == transport) .collect(Collectors.toList()); log("onDataProfileUnthrottled: dataProfile=" + dataProfile); Stream<DataThrottlingEntry> stream = mDataThrottlingEntries.stream(); stream = stream.filter(entry -> entry.expirationTimeMillis > now); if (dataProfile.getApnSetting() != null) { stream = stream .filter(entry -> entry.dataProfile.getApnSetting() != null) .filter(entry -> entry.dataProfile.getApnSetting().getApnName() .equals(dataProfile.getApnSetting().getApnName())); } stream = stream.filter(entry -> Objects.equals(entry.dataProfile.getTrafficDescriptor(), dataProfile.getTrafficDescriptor())); dataUnthrottlingEntries = stream.collect(Collectors.toList()); } else if (apn != null) { // For HIDL 1.6 or below dataUnthrottlingEntries = mDataThrottlingEntries.stream() Loading tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java +14 −22 Original line number Diff line number Diff line Loading @@ -129,7 +129,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.Executor; import java.util.stream.Collectors; @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper Loading Loading @@ -710,6 +709,20 @@ public class DataNetworkControllerTest extends TelephonyTest { mImsIwlanDataProfile, mEmergencyDataProfile, mFotaDataProfile, mTetheringDataProfile); 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]; Loading @@ -732,27 +745,6 @@ public class DataNetworkControllerTest extends TelephonyTest { doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).when(mAccessNetworksManager) .getPreferredTransportByNetworkCapability(anyInt()); doReturn(true).when(mDataProfileManager).isDataProfilePreferred(any(DataProfile.class)); doAnswer(invocation -> { String apnName = (String) invocation.getArguments()[0]; TrafficDescriptor td = (TrafficDescriptor) invocation.getArguments()[1]; List<DataProfile> dps = profiles; if (td != null) { dps = dps.stream() .filter(dp -> td.equals(dp.getTrafficDescriptor())) .collect(Collectors.toList()); } if (apnName != null) { dps = dps.stream() .filter(dp -> dp.getApnSetting() != null) .filter(dp -> apnName.equals(dp.getApnSetting().getApnName())) .collect(Collectors.toList()); } return dps.isEmpty() ? null : dps.get(0); }).when(mDataProfileManager).getDataProfile(anyString(), any()); doAnswer(invocation -> { ((Runnable) invocation.getArguments()[0]).run(); Loading tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java +40 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; import android.telephony.data.DataProfile; import android.telephony.data.TrafficDescriptor; import android.telephony.data.TrafficDescriptor.OsAppId; import android.test.mock.MockContentProvider; import android.test.mock.MockContentResolver; Loading Loading @@ -955,4 +956,43 @@ public class DataProfileManagerTest extends TelephonyTest { .filter(dp -> dp.canSatisfy(NetworkCapabilities.NET_CAPABILITY_IMS)) .collect(Collectors.toList())).hasSize(1); } @Test public void testDataProfileCompatibility() throws Exception { DataProfile enterpriseDataProfile = new DataProfile.Builder() .setTrafficDescriptor(new TrafficDescriptor(null, new TrafficDescriptor.OsAppId(TrafficDescriptor.OsAppId.ANDROID_OS_ID, "ENTERPRISE", 1).getBytes())) .build(); // Make sure the TD only profile is always compatible. assertThat(mDataProfileManagerUT.isDataProfileCompatible(enterpriseDataProfile)).isTrue(); // Make sure the profile which is slightly modified is also compatible. DataProfile dataProfile1 = new DataProfile.Builder() .setApnSetting(new ApnSetting.Builder() .setEntryName(GENERAL_PURPOSE_APN) .setId(1) .setApnName(GENERAL_PURPOSE_APN) .setProxyAddress("") .setMmsProxyAddress("") .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_MMS | ApnSetting.TYPE_SUPL | ApnSetting.TYPE_IA | ApnSetting.TYPE_FOTA) .setUser("") .setPassword("") .setAuthType(ApnSetting.AUTH_TYPE_NONE) .setProtocol(ApnSetting.PROTOCOL_IPV4V6) .setRoamingProtocol(ApnSetting.PROTOCOL_IPV4V6) .setCarrierEnabled(true) .setPersistent(true) .setMtuV4(1280) .setMtuV6(1280) .setNetworkTypeBitmask((int) (TelephonyManager.NETWORK_TYPE_BITMASK_LTE | TelephonyManager.NETWORK_TYPE_BITMASK_NR)) .setMvnoMatchData("") .build()) .build(); assertThat(mDataProfileManagerUT.isDataProfileCompatible(dataProfile1)).isTrue(); } } Loading
src/java/com/android/internal/telephony/data/DataNetworkController.java +4 −7 Original line number Diff line number Diff line Loading @@ -1743,13 +1743,10 @@ public class DataNetworkController extends Handler { evaluation.addDataDisallowedReason(DataDisallowedReason.DATA_DISABLED); } // Check if the data profile is still valid, sometimes the users can remove it from the APN // editor. We use very loose check here because APN id can change after APN reset to // default if (mDataProfileManager.getDataProfile( dataProfile.getApnSetting() != null ? dataProfile.getApnSetting().getApnName() : null, dataProfile.getTrafficDescriptor()) == null) { // Check if the data profile is still compatible, sometimes the users can remove it from the // APN editor. If some of the important fields are changed in APN settings, we need to // tear down the network. Note traffic descriptor from the data profile will not be checked. if (!mDataProfileManager.isDataProfileCompatible(dataProfile)) { evaluation.addDataDisallowedReason(DataDisallowedReason.DATA_PROFILE_INVALID); } Loading
src/java/com/android/internal/telephony/data/DataProfileManager.java +22 −28 Original line number Diff line number Diff line Loading @@ -86,7 +86,11 @@ public class DataProfileManager extends Handler { /** Cellular data service. */ private final @NonNull DataServiceManager mWwanDataServiceManager; /** All data profiles for the current carrier. */ /** * All data profiles for the current carrier. Note only data profiles loaded from the APN * database will be stored here. The on-demand data profiles (generated dynamically, for * example, enterprise data profiles with differentiator) are not stored here. */ private final @NonNull List<DataProfile> mAllDataProfiles = new ArrayList<>(); /** The data profile used for initial attach. */ Loading Loading @@ -911,39 +915,29 @@ public class DataProfileManager extends Handler { } /** * Get data profile by APN name and/or traffic descriptor. * * @param apnName APN name. * @param trafficDescriptor Traffic descriptor. * Check if the provided data profile is still compatible with the current environment. Note * this method ignores APN id check and traffic descriptor check. A data profile with traffic * descriptor only can always be used in any condition. * * @return Data profile by APN name and/or traffic descriptor. Either one of APN name or * traffic descriptor should be provided. {@code null} if data profile is not found. * @param dataProfile The data profile to check. * @return {@code true} if the provided data profile can be still used in current environment. */ public @Nullable DataProfile getDataProfile(@Nullable String apnName, @Nullable TrafficDescriptor trafficDescriptor) { if (apnName == null && trafficDescriptor == null) return null; List<DataProfile> dataProfiles = mAllDataProfiles; // Check if any existing data profile has the same traffic descriptor. if (trafficDescriptor != null) { dataProfiles = mAllDataProfiles.stream() .filter(dp -> trafficDescriptor.equals(dp.getTrafficDescriptor())) .collect(Collectors.toList()); public boolean isDataProfileCompatible(@NonNull DataProfile dataProfile) { if (dataProfile == null) { return false; } // Check if any existing data profile has the same APN name. if (apnName != null) { dataProfiles = dataProfiles.stream() .filter(dp -> dp.getApnSetting() != null && (dp.getApnSetting().getApnSetId() == Telephony.Carriers.MATCH_ALL_APN_SET_ID || dp.getApnSetting().getApnSetId() == mPreferredDataProfileSetId)) .filter(dp -> apnName.equals(dp.getApnSetting().getApnName())) .collect(Collectors.toList()); if (dataProfile.getApnSetting() == null && dataProfile.getTrafficDescriptor() != null) { // A traffic descriptor only data profile can be always used. Traffic descriptors are // always generated on the fly instead loaded from the database. return true; } return dataProfiles.isEmpty() ? null : dataProfiles.get(0); // Only check the APN from the profile is compatible or not. return mAllDataProfiles.stream() .filter(dp -> dp.getApnSetting() != null) .anyMatch(dp -> dp.getApnSetting().equals(dataProfile.getApnSetting(), mPhone.getServiceState().getDataRoamingFromRegistration())); } /** Loading
src/java/com/android/internal/telephony/data/DataRetryManager.java +13 −11 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ import java.util.UUID; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.Stream; /** * DataRetryManager manages data network setup retry and its configurations. Loading Loading @@ -1397,18 +1398,19 @@ public class DataRetryManager extends Handler { // equal to the data profiles kept in data profile manager (due to some fields missing // in DataProfileInfo.aidl), so we need to get the equivalent data profile from data // profile manager. final DataProfile dp = mDataProfileManager.getDataProfile( dataProfile.getApnSetting() != null ? dataProfile.getApnSetting().getApnName() : null, dataProfile.getTrafficDescriptor()); log("onDataProfileUnthrottled: getDataProfile=" + dp); if (dp != null) { dataUnthrottlingEntries = mDataThrottlingEntries.stream() .filter(entry -> entry.expirationTimeMillis > now && entry.dataProfile.equals(dp) && entry.transport == transport) .collect(Collectors.toList()); log("onDataProfileUnthrottled: dataProfile=" + dataProfile); Stream<DataThrottlingEntry> stream = mDataThrottlingEntries.stream(); stream = stream.filter(entry -> entry.expirationTimeMillis > now); if (dataProfile.getApnSetting() != null) { stream = stream .filter(entry -> entry.dataProfile.getApnSetting() != null) .filter(entry -> entry.dataProfile.getApnSetting().getApnName() .equals(dataProfile.getApnSetting().getApnName())); } stream = stream.filter(entry -> Objects.equals(entry.dataProfile.getTrafficDescriptor(), dataProfile.getTrafficDescriptor())); dataUnthrottlingEntries = stream.collect(Collectors.toList()); } else if (apn != null) { // For HIDL 1.6 or below dataUnthrottlingEntries = mDataThrottlingEntries.stream() Loading
tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java +14 −22 Original line number Diff line number Diff line Loading @@ -129,7 +129,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.Executor; import java.util.stream.Collectors; @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper Loading Loading @@ -710,6 +709,20 @@ public class DataNetworkControllerTest extends TelephonyTest { mImsIwlanDataProfile, mEmergencyDataProfile, mFotaDataProfile, mTetheringDataProfile); 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]; Loading @@ -732,27 +745,6 @@ public class DataNetworkControllerTest extends TelephonyTest { doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).when(mAccessNetworksManager) .getPreferredTransportByNetworkCapability(anyInt()); doReturn(true).when(mDataProfileManager).isDataProfilePreferred(any(DataProfile.class)); doAnswer(invocation -> { String apnName = (String) invocation.getArguments()[0]; TrafficDescriptor td = (TrafficDescriptor) invocation.getArguments()[1]; List<DataProfile> dps = profiles; if (td != null) { dps = dps.stream() .filter(dp -> td.equals(dp.getTrafficDescriptor())) .collect(Collectors.toList()); } if (apnName != null) { dps = dps.stream() .filter(dp -> dp.getApnSetting() != null) .filter(dp -> apnName.equals(dp.getApnSetting().getApnName())) .collect(Collectors.toList()); } return dps.isEmpty() ? null : dps.get(0); }).when(mDataProfileManager).getDataProfile(anyString(), any()); doAnswer(invocation -> { ((Runnable) invocation.getArguments()[0]).run(); Loading
tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java +40 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; import android.telephony.data.DataProfile; import android.telephony.data.TrafficDescriptor; import android.telephony.data.TrafficDescriptor.OsAppId; import android.test.mock.MockContentProvider; import android.test.mock.MockContentResolver; Loading Loading @@ -955,4 +956,43 @@ public class DataProfileManagerTest extends TelephonyTest { .filter(dp -> dp.canSatisfy(NetworkCapabilities.NET_CAPABILITY_IMS)) .collect(Collectors.toList())).hasSize(1); } @Test public void testDataProfileCompatibility() throws Exception { DataProfile enterpriseDataProfile = new DataProfile.Builder() .setTrafficDescriptor(new TrafficDescriptor(null, new TrafficDescriptor.OsAppId(TrafficDescriptor.OsAppId.ANDROID_OS_ID, "ENTERPRISE", 1).getBytes())) .build(); // Make sure the TD only profile is always compatible. assertThat(mDataProfileManagerUT.isDataProfileCompatible(enterpriseDataProfile)).isTrue(); // Make sure the profile which is slightly modified is also compatible. DataProfile dataProfile1 = new DataProfile.Builder() .setApnSetting(new ApnSetting.Builder() .setEntryName(GENERAL_PURPOSE_APN) .setId(1) .setApnName(GENERAL_PURPOSE_APN) .setProxyAddress("") .setMmsProxyAddress("") .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_MMS | ApnSetting.TYPE_SUPL | ApnSetting.TYPE_IA | ApnSetting.TYPE_FOTA) .setUser("") .setPassword("") .setAuthType(ApnSetting.AUTH_TYPE_NONE) .setProtocol(ApnSetting.PROTOCOL_IPV4V6) .setRoamingProtocol(ApnSetting.PROTOCOL_IPV4V6) .setCarrierEnabled(true) .setPersistent(true) .setMtuV4(1280) .setMtuV6(1280) .setNetworkTypeBitmask((int) (TelephonyManager.NETWORK_TYPE_BITMASK_LTE | TelephonyManager.NETWORK_TYPE_BITMASK_NR)) .setMvnoMatchData("") .build()) .build(); assertThat(mDataProfileManagerUT.isDataProfileCompatible(dataProfile1)).isTrue(); } }