Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 184e24b4 authored by Jack Yu's avatar Jack Yu Committed by Android (Google) Code Review
Browse files

Merge "Force MMS on IWLAN when needed" into main

parents 97671ee9 96359a4f
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -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"
}
+57 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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.
     */
@@ -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
@@ -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());
@@ -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())
+58 −1
Original line number Diff line number Diff line
@@ -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;
@@ -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)
@@ -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")
@@ -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))
@@ -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();
    }
}