Loading flags/data.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -104,3 +104,10 @@ flag { description: "The DataCallSessionStats metrics will capture whether the IWLAN PDN is set up on cross-SIM calling." bug: "313956117" } flag { name: "force_iwlan_mms" namespace: "telephony" description: "When QNS prefers MMS on IWLAN, MMS will be attempted on IWLAN if it can, even though if existing cellular network already supports MMS." bug: "316211526" } src/java/com/android/internal/telephony/data/DataNetwork.java +57 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkFactory; import android.net.NetworkProvider; import android.net.NetworkRequest; import android.net.NetworkScore; import android.net.ProxyInfo; import android.net.RouteInfo; Loading Loading @@ -91,6 +92,7 @@ import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.PhoneFactory; import com.android.internal.telephony.RIL; import com.android.internal.telephony.data.AccessNetworksManager.AccessNetworksManagerCallback; import com.android.internal.telephony.data.DataConfigManager.DataConfigManagerCallback; import com.android.internal.telephony.data.DataEvaluation.DataAllowedReason; import com.android.internal.telephony.data.DataNetworkController.NetworkRequestList; Loading Loading @@ -742,6 +744,11 @@ public class DataNetwork extends StateMachine { */ private @Nullable Consumer<Integer> mNetworkValidationResultCodeCallback; /** * Callback used to listen QNS preference changes. */ private @Nullable AccessNetworksManagerCallback mAccessNetworksManagerCallback; /** * The network bandwidth. */ Loading Loading @@ -1172,6 +1179,23 @@ public class DataNetwork extends StateMachine { getHandler(), EVENT_VOICE_CALL_ENDED, null); } if (mFlags.forceIwlanMms()) { if (mDataProfile.canSatisfy(NetworkCapabilities.NET_CAPABILITY_MMS)) { mAccessNetworksManagerCallback = new AccessNetworksManagerCallback( getHandler()::post) { @Override public void onPreferredTransportChanged( @NetCapability int networkCapability) { if (networkCapability == NetworkCapabilities.NET_CAPABILITY_MMS) { log("MMS preference changed."); updateNetworkCapabilities(); } } }; mAccessNetworksManager.registerCallback(mAccessNetworksManagerCallback); } } // Only add symmetric code here, for example, registering and unregistering. // DefaultState.enter() is the starting point in the life cycle of the DataNetwork, // and DefaultState.exit() is the end. For non-symmetric initializing works, put them Loading @@ -1181,6 +1205,10 @@ public class DataNetwork extends StateMachine { @Override public void exit() { logv("Unregistering all events."); if (mFlags.forceIwlanMms() && mAccessNetworksManagerCallback != null) { mAccessNetworksManager.unregisterCallback(mAccessNetworksManagerCallback); } // Check null for devices not supporting FEATURE_TELEPHONY_IMS. if (mPhone.getImsPhone() != null) { mPhone.getImsPhone().getCallTracker().unregisterForVoiceCallStarted(getHandler()); Loading Loading @@ -2333,6 +2361,35 @@ public class DataNetwork extends StateMachine { builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); } // Check if the feature force MMS on IWLAN is enabled. When the feature is enabled, MMS // will be attempted on IWLAN if possible, even if existing cellular networks already // supports IWLAN. if (mFlags.forceIwlanMms() && builder.build() .hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) { // If QNS sets MMS preferred on IWLAN, and it is possible to setup an MMS network on // IWLAN, then we need to remove the MMS capability on the cellular network. This will // allow the new MMS network to be brought up on IWLAN when MMS network request arrives. if (mAccessNetworksManager.getPreferredTransportByNetworkCapability( NetworkCapabilities.NET_CAPABILITY_MMS) == AccessNetworkConstants.TRANSPORT_TYPE_WLAN && mTransport == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) { DataProfile dataProfile = mDataNetworkController.getDataProfileManager() .getDataProfileForNetworkRequest(new TelephonyNetworkRequest( new NetworkRequest.Builder().addCapability( NetworkCapabilities.NET_CAPABILITY_MMS).build(), mPhone), TelephonyManager.NETWORK_TYPE_IWLAN, false, false, false); // If we find another data data profile that can support MMS on IWLAN, then remove // the MMS capability from this cellular network. This will allow IWLAN to be // brought up for MMS later. if (dataProfile != null && !dataProfile.equals(mDataProfile)) { log("Found a different data profile " + mDataProfile.getApn() + " that can serve MMS on IWLAN."); builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_MMS); } } } // If one of the capabilities are for special use, for example, IMS, CBS, then this // network should be restricted, regardless data is enabled or not. if (NetworkCapabilitiesUtils.inferRestrictedCapability(builder.build()) Loading tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java +58 −1 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ import android.util.SparseArray; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.TelephonyTest; import com.android.internal.telephony.data.AccessNetworksManager.AccessNetworksManagerCallback; import com.android.internal.telephony.data.DataConfigManager.DataConfigManagerCallback; import com.android.internal.telephony.data.DataEvaluation.DataAllowedReason; import com.android.internal.telephony.data.DataNetwork.DataNetworkCallback; Loading Loading @@ -123,7 +124,7 @@ public class DataNetworkTest extends TelephonyTest { .setApnName("fake_apn") .setUser("user") .setPassword("passwd") .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_SUPL) .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_SUPL | ApnSetting.TYPE_MMS) .setProtocol(ApnSetting.PROTOCOL_IPV6) .setRoamingProtocol(ApnSetting.PROTOCOL_IP) .setCarrierEnabled(true) Loading @@ -134,6 +135,18 @@ public class DataNetworkTest extends TelephonyTest { .setMaxConnsTime(789) .build(); private final ApnSetting mMmsApnSetting = new ApnSetting.Builder() .setId(2164) .setOperatorNumeric("12345") .setEntryName("fake_mms_apn") .setApnName("fake_mms_apn") .setApnTypeBitmask(ApnSetting.TYPE_MMS) .setProtocol(ApnSetting.PROTOCOL_IPV6) .setRoamingProtocol(ApnSetting.PROTOCOL_IP) .setCarrierEnabled(true) .setNetworkTypeBitmask((int) TelephonyManager.NETWORK_TYPE_BITMASK_IWLAN) .build(); private final ApnSetting mImsApnSetting = new ApnSetting.Builder() .setId(2163) .setOperatorNumeric("12345") Loading @@ -157,6 +170,11 @@ public class DataNetworkTest extends TelephonyTest { .setTrafficDescriptor(new TrafficDescriptor("fake_apn", null)) .build(); private final DataProfile mMmsDataProfile = new DataProfile.Builder() .setApnSetting(mMmsApnSetting) .setTrafficDescriptor(new TrafficDescriptor("fake_apn", null)) .build(); private final DataProfile mImsDataProfile = new DataProfile.Builder() .setApnSetting(mImsApnSetting) .setTrafficDescriptor(new TrafficDescriptor("fake_apn", null)) Loading Loading @@ -2203,4 +2221,43 @@ public class DataNetworkTest extends TelephonyTest { mDataNetworkUT, mDataCallSessionStats); processAllMessages(); } @Test public void testMmsCapabilityRemovedWhenMmsPreferredOnIwlan() throws Exception { doReturn(true).when(mFeatureFlags).forceIwlanMms(); setupDataNetwork(); assertThat(mDataNetworkUT.getNetworkCapabilities() .hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)).isTrue(); ArgumentCaptor<AccessNetworksManagerCallback> accessNetworksManagerCallbackArgumentCaptor = ArgumentCaptor.forClass(AccessNetworksManagerCallback.class); verify(mAccessNetworksManager).registerCallback( accessNetworksManagerCallbackArgumentCaptor.capture()); // Now QNS prefers MMS on IWLAN doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).when(mAccessNetworksManager) .getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_MMS); doReturn(mMmsDataProfile).when(mDataProfileManager).getDataProfileForNetworkRequest( any(TelephonyNetworkRequest.class), eq(TelephonyManager.NETWORK_TYPE_IWLAN), eq(false), eq(false), eq(false)); accessNetworksManagerCallbackArgumentCaptor.getValue() .onPreferredTransportChanged(NetworkCapabilities.NET_CAPABILITY_MMS); processAllMessages(); // Check if MMS capability is removed. assertThat(mDataNetworkUT.getNetworkCapabilities() .hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)).isFalse(); // Now QNS prefers MMS on IWLAN doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).when(mAccessNetworksManager) .getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_MMS); accessNetworksManagerCallbackArgumentCaptor.getValue() .onPreferredTransportChanged(NetworkCapabilities.NET_CAPABILITY_MMS); processAllMessages(); // Check if MMS capability is added back. assertThat(mDataNetworkUT.getNetworkCapabilities() .hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)).isTrue(); } } Loading
flags/data.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -104,3 +104,10 @@ flag { description: "The DataCallSessionStats metrics will capture whether the IWLAN PDN is set up on cross-SIM calling." bug: "313956117" } flag { name: "force_iwlan_mms" namespace: "telephony" description: "When QNS prefers MMS on IWLAN, MMS will be attempted on IWLAN if it can, even though if existing cellular network already supports MMS." bug: "316211526" }
src/java/com/android/internal/telephony/data/DataNetwork.java +57 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkFactory; import android.net.NetworkProvider; import android.net.NetworkRequest; import android.net.NetworkScore; import android.net.ProxyInfo; import android.net.RouteInfo; Loading Loading @@ -91,6 +92,7 @@ import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.PhoneFactory; import com.android.internal.telephony.RIL; import com.android.internal.telephony.data.AccessNetworksManager.AccessNetworksManagerCallback; import com.android.internal.telephony.data.DataConfigManager.DataConfigManagerCallback; import com.android.internal.telephony.data.DataEvaluation.DataAllowedReason; import com.android.internal.telephony.data.DataNetworkController.NetworkRequestList; Loading Loading @@ -742,6 +744,11 @@ public class DataNetwork extends StateMachine { */ private @Nullable Consumer<Integer> mNetworkValidationResultCodeCallback; /** * Callback used to listen QNS preference changes. */ private @Nullable AccessNetworksManagerCallback mAccessNetworksManagerCallback; /** * The network bandwidth. */ Loading Loading @@ -1172,6 +1179,23 @@ public class DataNetwork extends StateMachine { getHandler(), EVENT_VOICE_CALL_ENDED, null); } if (mFlags.forceIwlanMms()) { if (mDataProfile.canSatisfy(NetworkCapabilities.NET_CAPABILITY_MMS)) { mAccessNetworksManagerCallback = new AccessNetworksManagerCallback( getHandler()::post) { @Override public void onPreferredTransportChanged( @NetCapability int networkCapability) { if (networkCapability == NetworkCapabilities.NET_CAPABILITY_MMS) { log("MMS preference changed."); updateNetworkCapabilities(); } } }; mAccessNetworksManager.registerCallback(mAccessNetworksManagerCallback); } } // Only add symmetric code here, for example, registering and unregistering. // DefaultState.enter() is the starting point in the life cycle of the DataNetwork, // and DefaultState.exit() is the end. For non-symmetric initializing works, put them Loading @@ -1181,6 +1205,10 @@ public class DataNetwork extends StateMachine { @Override public void exit() { logv("Unregistering all events."); if (mFlags.forceIwlanMms() && mAccessNetworksManagerCallback != null) { mAccessNetworksManager.unregisterCallback(mAccessNetworksManagerCallback); } // Check null for devices not supporting FEATURE_TELEPHONY_IMS. if (mPhone.getImsPhone() != null) { mPhone.getImsPhone().getCallTracker().unregisterForVoiceCallStarted(getHandler()); Loading Loading @@ -2333,6 +2361,35 @@ public class DataNetwork extends StateMachine { builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); } // Check if the feature force MMS on IWLAN is enabled. When the feature is enabled, MMS // will be attempted on IWLAN if possible, even if existing cellular networks already // supports IWLAN. if (mFlags.forceIwlanMms() && builder.build() .hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) { // If QNS sets MMS preferred on IWLAN, and it is possible to setup an MMS network on // IWLAN, then we need to remove the MMS capability on the cellular network. This will // allow the new MMS network to be brought up on IWLAN when MMS network request arrives. if (mAccessNetworksManager.getPreferredTransportByNetworkCapability( NetworkCapabilities.NET_CAPABILITY_MMS) == AccessNetworkConstants.TRANSPORT_TYPE_WLAN && mTransport == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) { DataProfile dataProfile = mDataNetworkController.getDataProfileManager() .getDataProfileForNetworkRequest(new TelephonyNetworkRequest( new NetworkRequest.Builder().addCapability( NetworkCapabilities.NET_CAPABILITY_MMS).build(), mPhone), TelephonyManager.NETWORK_TYPE_IWLAN, false, false, false); // If we find another data data profile that can support MMS on IWLAN, then remove // the MMS capability from this cellular network. This will allow IWLAN to be // brought up for MMS later. if (dataProfile != null && !dataProfile.equals(mDataProfile)) { log("Found a different data profile " + mDataProfile.getApn() + " that can serve MMS on IWLAN."); builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_MMS); } } } // If one of the capabilities are for special use, for example, IMS, CBS, then this // network should be restricted, regardless data is enabled or not. if (NetworkCapabilitiesUtils.inferRestrictedCapability(builder.build()) Loading
tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java +58 −1 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ import android.util.SparseArray; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.TelephonyTest; import com.android.internal.telephony.data.AccessNetworksManager.AccessNetworksManagerCallback; import com.android.internal.telephony.data.DataConfigManager.DataConfigManagerCallback; import com.android.internal.telephony.data.DataEvaluation.DataAllowedReason; import com.android.internal.telephony.data.DataNetwork.DataNetworkCallback; Loading Loading @@ -123,7 +124,7 @@ public class DataNetworkTest extends TelephonyTest { .setApnName("fake_apn") .setUser("user") .setPassword("passwd") .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_SUPL) .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_SUPL | ApnSetting.TYPE_MMS) .setProtocol(ApnSetting.PROTOCOL_IPV6) .setRoamingProtocol(ApnSetting.PROTOCOL_IP) .setCarrierEnabled(true) Loading @@ -134,6 +135,18 @@ public class DataNetworkTest extends TelephonyTest { .setMaxConnsTime(789) .build(); private final ApnSetting mMmsApnSetting = new ApnSetting.Builder() .setId(2164) .setOperatorNumeric("12345") .setEntryName("fake_mms_apn") .setApnName("fake_mms_apn") .setApnTypeBitmask(ApnSetting.TYPE_MMS) .setProtocol(ApnSetting.PROTOCOL_IPV6) .setRoamingProtocol(ApnSetting.PROTOCOL_IP) .setCarrierEnabled(true) .setNetworkTypeBitmask((int) TelephonyManager.NETWORK_TYPE_BITMASK_IWLAN) .build(); private final ApnSetting mImsApnSetting = new ApnSetting.Builder() .setId(2163) .setOperatorNumeric("12345") Loading @@ -157,6 +170,11 @@ public class DataNetworkTest extends TelephonyTest { .setTrafficDescriptor(new TrafficDescriptor("fake_apn", null)) .build(); private final DataProfile mMmsDataProfile = new DataProfile.Builder() .setApnSetting(mMmsApnSetting) .setTrafficDescriptor(new TrafficDescriptor("fake_apn", null)) .build(); private final DataProfile mImsDataProfile = new DataProfile.Builder() .setApnSetting(mImsApnSetting) .setTrafficDescriptor(new TrafficDescriptor("fake_apn", null)) Loading Loading @@ -2203,4 +2221,43 @@ public class DataNetworkTest extends TelephonyTest { mDataNetworkUT, mDataCallSessionStats); processAllMessages(); } @Test public void testMmsCapabilityRemovedWhenMmsPreferredOnIwlan() throws Exception { doReturn(true).when(mFeatureFlags).forceIwlanMms(); setupDataNetwork(); assertThat(mDataNetworkUT.getNetworkCapabilities() .hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)).isTrue(); ArgumentCaptor<AccessNetworksManagerCallback> accessNetworksManagerCallbackArgumentCaptor = ArgumentCaptor.forClass(AccessNetworksManagerCallback.class); verify(mAccessNetworksManager).registerCallback( accessNetworksManagerCallbackArgumentCaptor.capture()); // Now QNS prefers MMS on IWLAN doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).when(mAccessNetworksManager) .getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_MMS); doReturn(mMmsDataProfile).when(mDataProfileManager).getDataProfileForNetworkRequest( any(TelephonyNetworkRequest.class), eq(TelephonyManager.NETWORK_TYPE_IWLAN), eq(false), eq(false), eq(false)); accessNetworksManagerCallbackArgumentCaptor.getValue() .onPreferredTransportChanged(NetworkCapabilities.NET_CAPABILITY_MMS); processAllMessages(); // Check if MMS capability is removed. assertThat(mDataNetworkUT.getNetworkCapabilities() .hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)).isFalse(); // Now QNS prefers MMS on IWLAN doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).when(mAccessNetworksManager) .getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_MMS); accessNetworksManagerCallbackArgumentCaptor.getValue() .onPreferredTransportChanged(NetworkCapabilities.NET_CAPABILITY_MMS); processAllMessages(); // Check if MMS capability is added back. assertThat(mDataNetworkUT.getNetworkCapabilities() .hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)).isTrue(); } }