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

Commit 4dfbe5ec authored by Jack Yu's avatar Jack Yu Committed by Automerger Merge Worker
Browse files

Merge "Fixed that data network not entering disconnecting" into tm-dev am: 0775c5fa

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/opt/telephony/+/17323739

Change-Id: I50335d1c009c3bf9e0b6406efb2d5158499a3c1a
parents c8058ca5 0775c5fa
Loading
Loading
Loading
Loading
+29 −4
Original line number Diff line number Diff line
@@ -210,6 +210,12 @@ public class DataNetwork extends StateMachine {
     */
    private static final int EVENT_STUCK_IN_TRANSIENT_STATE = 20;

    /**
     * Event for waiting for tearing down condition met. This will cause data network entering
     * disconnecting state.
     */
    private static final int EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET = 21;

    /** The default MTU for IPv4 network. */
    private static final int DEFAULT_MTU_V4 = 1280;

@@ -985,7 +991,9 @@ public class DataNetwork extends StateMachine {
                case EVENT_PCO_DATA_RECEIVED:
                case EVENT_STUCK_IN_TRANSIENT_STATE:
                case EVENT_DISPLAY_INFO_CHANGED:
                case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET:
                    // Ignore the events when not in the correct state.
                    log("Ignored " + eventToString(msg.what));
                    break;
                case EVENT_START_HANDOVER:
                    log("Ignore the handover to " + AccessNetworkConstants
@@ -1058,6 +1066,7 @@ public class DataNetwork extends StateMachine {
                case EVENT_START_HANDOVER:
                case EVENT_TEAR_DOWN_NETWORK:
                case EVENT_PCO_DATA_RECEIVED:
                case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET:
                    // Defer the request until connected or disconnected.
                    deferMessage(msg);
                    break;
@@ -1177,6 +1186,10 @@ public class DataNetwork extends StateMachine {
                    int resultCode = msg.arg1;
                    onDeactivateResponse(resultCode);
                    break;
                case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET:
                    transitionTo(mDisconnectingState);
                    sendMessageDelayed(EVENT_TEAR_DOWN_NETWORK, msg.arg1, msg.arg2);
                    break;
                default:
                    return NOT_HANDLED;
            }
@@ -1214,6 +1227,7 @@ public class DataNetwork extends StateMachine {
                        deferMessage(msg);
                    }
                    break;
                case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET:
                case EVENT_DISPLAY_INFO_CHANGED:
                case EVENT_TEAR_DOWN_NETWORK:
                    // Defer the request until handover succeeds or fails.
@@ -1315,6 +1329,15 @@ public class DataNetwork extends StateMachine {
        public boolean processMessage(Message msg) {
            logv("event=" + eventToString(msg.what));
            switch (msg.what) {
                case EVENT_TEAR_DOWN_NETWORK:
                    if (mInvokedDataDeactivation) {
                        log("Ignore tear down request because network is being torn down.");
                        break;
                    }
                    removeMessages(EVENT_TEAR_DOWN_NETWORK);
                    removeDeferredMessages(EVENT_TEAR_DOWN_NETWORK);
                    onTearDown(msg.arg1);
                    break;
                case EVENT_DEACTIVATE_DATA_NETWORK_RESPONSE:
                    int resultCode = msg.arg1;
                    onDeactivateResponse(resultCode);
@@ -2159,15 +2182,15 @@ public class DataNetwork extends StateMachine {
     * will be performed. {@code null} if the data network is already disconnected or being
     * disconnected.
     */
    public @Nullable Runnable tearDownWithCondition(@TearDownReason int reason,
    public @Nullable Runnable tearDownWhenConditionMet(@TearDownReason int reason,
            long timeoutMillis) {
        if (getCurrentState() == null || isDisconnected() || isDisconnecting()) {
            loge("tearDownGracefully: Not in the right state. State=" + getCurrentState());
            loge("tearDownWhenConditionMet: Not in the right state. State=" + getCurrentState());
            return null;
        }
        logl("tearDownWithCondition: reason=" + tearDownReasonToString(reason) + ", timeout="
        logl("tearDownWhenConditionMet: reason=" + tearDownReasonToString(reason) + ", timeout="
                + timeoutMillis + "ms.");
        sendMessageDelayed(EVENT_TEAR_DOWN_NETWORK, reason, timeoutMillis);
        sendMessage(EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET, reason, (int) timeoutMillis);
        return () -> this.tearDown(reason);
    }

@@ -2865,6 +2888,8 @@ public class DataNetwork extends StateMachine {
                return "EVENT_DEACTIVATE_DATA_NETWORK_RESPONSE";
            case EVENT_STUCK_IN_TRANSIENT_STATE:
                return "EVENT_STUCK_IN_TRANSIENT_STATE";
            case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET:
                return "EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET";
            default:
                return "Unknown(" + event + ")";
        }
+4 −5
Original line number Diff line number Diff line
@@ -867,9 +867,8 @@ public class DataNetworkController extends Handler {
            }
        });

        mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(
                AccessNetworkConstants.TRANSPORT_TYPE_WWAN, this, EVENT_SERVICE_STATE_CHANGED,
                AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
        mPhone.getServiceStateTracker().registerForServiceStateChanged(this,
                EVENT_SERVICE_STATE_CHANGED);
        mDataConfigManager.registerForConfigUpdate(this, EVENT_DATA_CONFIG_UPDATED);
        mPhone.getServiceStateTracker().registerForPsRestrictedEnabled(this,
                EVENT_PS_RESTRICT_ENABLED, null);
@@ -1899,7 +1898,7 @@ public class DataNetworkController extends Handler {
    }

    /**
     * Unregister IMS faeture state callbacks.
     * Unregister IMS feature state callbacks.
     *
     * @param subId Subscription index.
     */
@@ -2983,7 +2982,7 @@ public class DataNetworkController extends Handler {
                    ? "registered" : "not registered")
            );
            mPendingImsDeregDataNetworks.put(dataNetwork,
                    dataNetwork.tearDownWithCondition(reason, deregDelay));
                    dataNetwork.tearDownWhenConditionMet(reason, deregDelay));
        } else {
            // Graceful tear down is not turned on. Tear down the network immediately.
            log("tearDownGracefully: Safe to tear down " + dataNetwork);
+149 −6
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ import android.telephony.DataSpecificRegistrationInfo;
import android.telephony.LteVopsSupportInfo;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.NetworkRegistrationInfo.RegistrationState;
import android.telephony.PreciseDataConnectionState;
import android.telephony.ServiceState;
import android.telephony.SubscriptionPlan;
import android.telephony.TelephonyManager;
@@ -77,6 +78,15 @@ import android.telephony.data.DataCallResponse.LinkStatus;
import android.telephony.data.DataProfile;
import android.telephony.data.DataServiceCallback;
import android.telephony.data.ThrottleStatus;
import android.telephony.ims.ImsManager;
import android.telephony.ims.ImsMmTelManager;
import android.telephony.ims.ImsRcsManager;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ImsRegistrationAttributes;
import android.telephony.ims.ImsStateCallback;
import android.telephony.ims.RegistrationManager.RegistrationCallback;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.ArraySet;
@@ -89,6 +99,7 @@ import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.data.AccessNetworksManager.AccessNetworksManagerCallback;
import com.android.internal.telephony.data.DataNetworkController.HandoverRule;
import com.android.internal.telephony.data.DataRetryManager.DataRetryManagerCallback;
import com.android.internal.telephony.ims.ImsResolver;

import org.junit.After;
import org.junit.Before;
@@ -114,11 +125,23 @@ public class DataNetworkControllerTest extends TelephonyTest {
    private static final String IPV4_ADDRESS = "10.0.2.15";
    private static final String IPV6_ADDRESS = "2607:fb90:a620:651d:eabe:f8da:c107:44be";

    private static final String FAKE_MMTEL_PACKAGE = "fake.mmtel.package";
    private static final String FAKE_RCS_PACKAGE = "fake.rcs.package";

    // Mocked classes
    private PhoneSwitcher mMockedPhoneSwitcher;
    protected ISub mIsub;
    protected ISub mMockedIsub;
    private DataNetworkControllerCallback mMockedDataNetworkControllerCallback;
    private DataRetryManagerCallback mMockedDataRetryManagerCallback;
    private ImsResolver mMockedImsResolver;

    private ImsManager mMockedImsManager;
    private ImsMmTelManager mMockedImsMmTelManager;
    private ImsRcsManager mMockedImsRcsManager;
    private ImsStateCallback mMmtelStateCallback;
    private ImsStateCallback mRcsStateCallback;
    private RegistrationCallback mMmtelRegCallback;
    private RegistrationCallback mRcsRegCallback;

    private int mNetworkRequestId = 0;

@@ -333,6 +356,36 @@ public class DataNetworkControllerTest extends TelephonyTest {
        processAllMessages();
    }

    private void setImsRegistered(boolean registered) {
        if (registered) {
            final ArraySet<String> features = new ArraySet<>();
            features.add("feature1");
            features.add("feature2");
            ImsRegistrationAttributes attr = new ImsRegistrationAttributes.Builder(
                    ImsRegistrationImplBase.REGISTRATION_TECH_LTE).setFeatureTags(features).build();

            mMmtelRegCallback.onRegistered(attr);
        } else {
            ImsReasonInfo info = new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE, -1, "");
            mMmtelRegCallback.onUnregistered(info);
        }
    }

    private void setRcsRegistered(boolean registered) {
        if (registered) {
            final ArraySet<String> features = new ArraySet<>();
            features.add("feature1");
            features.add("feature2");
            ImsRegistrationAttributes attr = new ImsRegistrationAttributes.Builder(
                    ImsRegistrationImplBase.REGISTRATION_TECH_LTE).setFeatureTags(features).build();

            mRcsRegCallback.onRegistered(attr);
        } else {
            ImsReasonInfo info = new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE, -1, "");
            mRcsRegCallback.onUnregistered(info);
        }
    }

    private void serviceStateChanged(@NetworkType int networkType,
            @RegistrationState int regState) {
        serviceStateChanged(networkType, regState, null);
@@ -425,6 +478,9 @@ public class DataNetworkControllerTest extends TelephonyTest {

        mContextFixture.putResource(com.android.internal.R.string.config_bandwidthEstimateSource,
                "bandwidth_estimator");

        mContextFixture.putIntResource(com.android.internal.R.integer
                        .config_delay_for_ims_dereg_millis, 3000);
    }

    @Before
@@ -432,12 +488,18 @@ public class DataNetworkControllerTest extends TelephonyTest {
        logd("DataNetworkControllerTest +Setup!");
        super.setUp(getClass().getSimpleName());
        mMockedPhoneSwitcher = Mockito.mock(PhoneSwitcher.class);
        mIsub = Mockito.mock(ISub.class);
        mMockedIsub = Mockito.mock(ISub.class);
        mMockedImsManager = mContext.getSystemService(ImsManager.class);
        mMockedImsMmTelManager = Mockito.mock(ImsMmTelManager.class);
        mMockedImsRcsManager = Mockito.mock(ImsRcsManager.class);
        mMockedImsResolver = Mockito.mock(ImsResolver.class);
        mMockedDataNetworkControllerCallback = Mockito.mock(DataNetworkControllerCallback.class);
        mMockedDataRetryManagerCallback = Mockito.mock(DataRetryManagerCallback.class);
        when(mTelephonyComponentFactory.makeDataSettingsManager(any(Phone.class),
                any(DataNetworkController.class), any(Looper.class),
                any(DataSettingsManager.DataSettingsManagerCallback.class))).thenCallRealMethod();
        doReturn(mMockedImsMmTelManager).when(mMockedImsManager).getImsMmTelManager(anyInt());
        doReturn(mMockedImsRcsManager).when(mMockedImsManager).getImsRcsManager(anyInt());

        initializeConfig();
        mMockedDataServiceManagers.put(AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
@@ -446,8 +508,8 @@ public class DataNetworkControllerTest extends TelephonyTest {
                mMockedWlanDataServiceManager);

        replaceInstance(PhoneSwitcher.class, "sPhoneSwitcher", null, mMockedPhoneSwitcher);
        doReturn(1).when(mIsub).getDefaultDataSubId();
        doReturn(mIsub).when(mIBinder).queryLocalInterface(anyString());
        doReturn(1).when(mMockedIsub).getDefaultDataSubId();
        doReturn(mMockedIsub).when(mIBinder).queryLocalInterface(anyString());
        doReturn(mPhone).when(mPhone).getImsPhone();
        mServiceManagerMockedServices.put("isub", mIBinder);
        doReturn(new SubscriptionPlan[]{}).when(mNetworkPolicyManager)
@@ -481,6 +543,8 @@ public class DataNetworkControllerTest extends TelephonyTest {
                    Handler.class), anyInt());
        }

        doReturn(-1).when(mPhone).getSubId();

        // Note that creating a "real" data network controller will also result in creating
        // real DataRetryManager, DataConfigManager, etc...Normally in unit test we should isolate
        // other modules and make them mocked, but only focusing on testing the unit we would like
@@ -489,6 +553,10 @@ public class DataNetworkControllerTest extends TelephonyTest {
        // as well, except some modules below we replaced with mocks.
        mDataNetworkControllerUT = new DataNetworkController(mPhone, Looper.myLooper());
        doReturn(mDataNetworkControllerUT).when(mPhone).getDataNetworkController();

        doReturn(1).when(mPhone).getSubId();
        mDataNetworkControllerUT.obtainMessage(15/*EVENT_SUBSCRIPTION_CHANGED*/).sendToTarget();

        processAllMessages();
        // Clear the callbacks created by the real sub-modules created by DataNetworkController.
        clearCallbacks();
@@ -503,6 +571,7 @@ public class DataNetworkControllerTest extends TelephonyTest {
                mDataNetworkControllerUT, mDataProfileManager);
        replaceInstance(DataNetworkController.class, "mAccessNetworksManager",
                mDataNetworkControllerUT, mAccessNetworksManager);
        replaceInstance(ImsResolver.class, "sInstance", null, mMockedImsResolver);

        ArgumentCaptor<AccessNetworksManagerCallback> callbackCaptor =
                ArgumentCaptor.forClass(AccessNetworksManagerCallback.class);
@@ -555,11 +624,41 @@ public class DataNetworkControllerTest extends TelephonyTest {
                new AsyncResult(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, true, null))
                .sendToTarget();

        ArgumentCaptor<ImsStateCallback> imsCallbackCaptor =
                ArgumentCaptor.forClass(ImsStateCallback.class);
        verify(mMockedImsMmTelManager).registerImsStateCallback(any(Executor.class),
                imsCallbackCaptor.capture());
        mMmtelStateCallback = imsCallbackCaptor.getValue();

        verify(mMockedImsRcsManager).registerImsStateCallback(any(Executor.class),
                imsCallbackCaptor.capture());
        mRcsStateCallback = imsCallbackCaptor.getValue();

        carrierConfigChanged();

        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);

        // IMS registration
        doReturn(FAKE_MMTEL_PACKAGE).when(mMockedImsResolver).getConfiguredImsServicePackageName(
                anyInt(), eq(ImsFeature.FEATURE_MMTEL));
        doReturn(FAKE_RCS_PACKAGE).when(mMockedImsResolver).getConfiguredImsServicePackageName(
                anyInt(), eq(ImsFeature.FEATURE_RCS));

        mMmtelStateCallback.onAvailable();
        mRcsStateCallback.onAvailable();

        ArgumentCaptor<RegistrationCallback> regCallbackCaptor =
                ArgumentCaptor.forClass(RegistrationCallback.class);

        verify(mMockedImsMmTelManager).registerImsRegistrationCallback(any(Executor.class),
                regCallbackCaptor.capture());
        mMmtelRegCallback = regCallbackCaptor.getValue();

        verify(mMockedImsRcsManager).registerImsRegistrationCallback(any(Executor.class),
                regCallbackCaptor.capture());
        mRcsRegCallback = regCallbackCaptor.getValue();

        processAllMessages();

        logd("DataNetworkControllerTest -Setup!");
@@ -739,7 +838,6 @@ public class DataNetworkControllerTest extends TelephonyTest {
        verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS);
        verifyConnectedNetworkHasDataProfile(mImsDataProfile);
        List<DataNetwork> dataNetworkList = getDataNetworks();
        DataNetwork dataNetwork = dataNetworkList.get(0);
        assertThat(dataNetworkList.get(0).getLinkProperties().getAddresses()).containsExactly(
                InetAddresses.parseNumericAddress(IPV4_ADDRESS),
                InetAddresses.parseNumericAddress(IPV6_ADDRESS));
@@ -1918,4 +2016,49 @@ public class DataNetworkControllerTest extends TelephonyTest {
        verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_DUN);
        verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA);
    }

    @Test
    public void testImsGracefulTearDown() throws Exception {
        setImsRegistered(true);
        setRcsRegistered(true);

        NetworkCapabilities netCaps = new NetworkCapabilities();
        netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
        netCaps.setRequestorPackageName(FAKE_MMTEL_PACKAGE);

        NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps,
                ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId, NetworkRequest.Type.REQUEST);
        TelephonyNetworkRequest networkRequest = new TelephonyNetworkRequest(
                nativeNetworkRequest, mPhone);

        mDataNetworkControllerUT.addNetworkRequest(networkRequest);

        processAllMessages();
        Mockito.clearInvocations(mPhone);

        // SIM removal
        mDataNetworkControllerUT.obtainMessage(9/*EVENT_SIM_STATE_CHANGED*/,
                TelephonyManager.SIM_STATE_ABSENT, 0).sendToTarget();
        processAllMessages();

        // Make sure data network enters disconnecting state
        ArgumentCaptor<PreciseDataConnectionState> pdcsCaptor =
                ArgumentCaptor.forClass(PreciseDataConnectionState.class);
        verify(mPhone).notifyDataConnection(pdcsCaptor.capture());
        PreciseDataConnectionState pdcs = pdcsCaptor.getValue();
        assertThat(pdcs.getState()).isEqualTo(TelephonyManager.DATA_DISCONNECTING);

        // IMS de-registered. Now data network is safe to be torn down.
        Mockito.clearInvocations(mPhone);
        setImsRegistered(false);
        setRcsRegistered(false);
        processAllMessages();

        // All data should be disconnected.
        verifyAllDataDisconnected();
        verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
        verify(mPhone).notifyDataConnection(pdcsCaptor.capture());
        pdcs = pdcsCaptor.getValue();
        assertThat(pdcs.getState()).isEqualTo(TelephonyManager.DATA_DISCONNECTED);
    }
}