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

Commit 88a2e928 authored by Chi Zhang's avatar Chi Zhang
Browse files

Use IMS registration for voice RAT stats.

Bug: 196260972
Test: build and atest
Change-Id: I18db33558de94485497c6d75add60796b6b8eb79
Merged-In: I18db33558de94485497c6d75add60796b6b8eb79
(cherry picked from commit 69e548b0)
parent 9b2f80a9
Loading
Loading
Loading
Loading
+31 −12
Original line number Diff line number Diff line
@@ -35,8 +35,6 @@ import android.os.SystemClock;
import android.telephony.AccessNetworkConstants;
import android.telephony.AccessNetworkConstants.TransportType;
import android.telephony.Annotation.NetworkType;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ProvisioningManager;
@@ -265,10 +263,24 @@ public class ImsStats {
            @ImsRegistrationTech int radioTech, MmTelCapabilities capabilities) {
        conclude();

        if (mLastRegistrationStats != null) {
            mLastRegistrationStats.rat = convertRegistrationTechToNetworkType(radioTech);
        boolean ratChanged = false;
        @NetworkType int newRat = convertRegistrationTechToNetworkType(radioTech);
        if (mLastRegistrationStats != null && mLastRegistrationStats.rat != newRat) {
            mLastRegistrationStats.rat = newRat;
            ratChanged = true;
        }

        boolean voiceAvailableNow = capabilities.isCapable(CAPABILITY_TYPE_VOICE);
        boolean voiceAvailabilityChanged =
                (mLastAvailableFeatures.isCapable(CAPABILITY_TYPE_VOICE) != voiceAvailableNow);
        mLastAvailableFeatures = capabilities;

        // Notify voice RAT change if 1. RAT changed while voice over IMS is available, or 2. voice
        // over IMS availability changed
        if ((ratChanged && voiceAvailableNow) || voiceAvailabilityChanged) {
            mPhone.getDefaultPhone().getServiceStateTracker().getServiceStateStats()
                    .onImsVoiceRegistrationChanged();
        }
    }

    /** Updates the stats when capable features changed. */
@@ -335,6 +347,20 @@ public class ImsStats {
        mLastAvailableFeatures = new MmTelCapabilities();
    }

    /**
     * Returns the current RAT used for IMS voice registration, or {@link
     * TelephonyManager#NETWORK_TYPE_UNKNOWN} if there isn't any.
     */
    @NetworkType
    @VisibleForTesting
    public synchronized int getImsVoiceRadioTech() {
        if (mLastRegistrationStats == null
                || !mLastAvailableFeatures.isCapable(CAPABILITY_TYPE_VOICE)) {
            return TelephonyManager.NETWORK_TYPE_UNKNOWN;
        }
        return mLastRegistrationStats.rat;
    }

    @NetworkType
    private int getRatAtEnd(@NetworkType int lastStateRat) {
        return lastStateRat == TelephonyManager.NETWORK_TYPE_IWLAN ? lastStateRat : getWwanPsRat();
@@ -354,14 +380,7 @@ public class ImsStats {

    @NetworkType
    private int getWwanPsRat() {
        ServiceState state = mPhone.getServiceStateTracker().getServiceState();
        final NetworkRegistrationInfo wwanRegInfo =
                state.getNetworkRegistrationInfo(
                        NetworkRegistrationInfo.DOMAIN_PS,
                        AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
        return wwanRegInfo != null
                ? wwanRegInfo.getAccessNetworkTechnology()
                : TelephonyManager.NETWORK_TYPE_UNKNOWN;
        return ServiceStateStats.getDataRat(mPhone.getServiceStateTracker().getServiceState());
    }

    private ImsRegistrationStats getDefaultImsRegistrationStats() {
+30 −9
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch;
import com.android.internal.telephony.nano.PersistAtomsProto.CellularServiceState;
import com.android.telephony.Rlog;
@@ -58,6 +59,23 @@ public class ServiceStateStats {
        addServiceState(lastState, now);
    }

    /** Updates service state when IMS voice registration changes. */
    public void onImsVoiceRegistrationChanged() {
        final long now = getTimeMillis();
        TimestampedServiceState lastState =
                mLastState.getAndUpdate(
                        state -> {
                            if (state.mServiceState == null) {
                                return new TimestampedServiceState(null, now);
                            }
                            CellularServiceState newServiceState = copyOf(state.mServiceState);
                            newServiceState.voiceRat =
                                    getVoiceRat(mPhone, getServiceStateForPhone(mPhone));
                            return new TimestampedServiceState(newServiceState, now);
                        });
        addServiceState(lastState, now);
    }

    /** Updates the current service state. */
    public void onServiceStateChanged(ServiceState serviceState) {
        final long now = getTimeMillis();
@@ -209,18 +227,21 @@ public class ServiceStateStats {
    }

    /**
     * Returns the current voice RAT from the service state, or {@link
     * TelephonyManager#NETWORK_TYPE_IWLAN} if the phone has Wifi calling in use.
     * Returns the current voice RAT from IMS registration if present, otherwise from the service
     * state.
     */
    public static @NetworkType int getVoiceRat(Phone phone, @Nullable ServiceState state) {
    static @NetworkType int getVoiceRat(Phone phone, @Nullable ServiceState state) {
        if (state == null) {
            return TelephonyManager.NETWORK_TYPE_UNKNOWN;
        }
        boolean isWifiCall =
                phone.getImsPhone() != null
                        && phone.getImsPhone().isWifiCallingEnabled()
                        && state.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_IWLAN;
        return isWifiCall ? TelephonyManager.NETWORK_TYPE_IWLAN : state.getVoiceNetworkType();
        ImsPhone imsPhone = (ImsPhone) phone.getImsPhone();
        if (imsPhone != null) {
            @NetworkType int imsVoiceRat = imsPhone.getImsStats().getImsVoiceRadioTech();
            if (imsVoiceRat != TelephonyManager.NETWORK_TYPE_UNKNOWN) {
                return imsVoiceRat;
            }
        }
        return state.getVoiceNetworkType();
    }

    /**
@@ -237,7 +258,7 @@ public class ServiceStateStats {
    }

    /** Returns PS (data) RAT used by WWAN. */
    private static @NetworkType int getDataRat(ServiceState state) {
    static @NetworkType int getDataRat(ServiceState state) {
        final NetworkRegistrationInfo wwanRegInfo =
                state.getNetworkRegistrationInfo(
                        NetworkRegistrationInfo.DOMAIN_PS,
+141 −0
Original line number Diff line number Diff line
@@ -25,11 +25,13 @@ import static android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPAB
import static android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE;
import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN;
import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_LTE;
import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_NR;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -76,6 +78,7 @@ public class ImsStatsTest extends TelephonyTest {
    @Mock private UiccSlot mPhysicalSlot1;
    @Mock private Phone mSecondPhone;
    @Mock private ImsPhone mSecondImsPhone;
    @Mock private ServiceStateStats mServiceStateStats;

    private TestableImsStats mImsStats;

@@ -109,6 +112,7 @@ public class ImsStatsTest extends TelephonyTest {
        doReturn(CARRIER1_ID).when(mPhone).getCarrierId();
        doReturn(mImsPhone).when(mPhone).getImsPhone();
        doReturn(mSST).when(mImsPhone).getServiceStateTracker();
        doReturn(mServiceStateStats).when(mSST).getServiceStateStats();

        // WWAN PS RAT is LTE
        doReturn(
@@ -338,6 +342,86 @@ public class ImsStatsTest extends TelephonyTest {
        assertEquals(0L, stats.smsCapableMillis);
        assertEquals(0L, stats.smsAvailableMillis);
        verifyNoMoreInteractions(mPersistAtomsStorage);
        // ServiceStateStats should be notified
        verify(mServiceStateStats).onImsVoiceRegistrationChanged();
    }

    @Test
    @SmallTest
    public void onImsCapabilitiesChanged_differentTech() throws Exception {
        mImsStats.onSetFeatureResponse(
                CAPABILITY_TYPE_VOICE,
                REGISTRATION_TECH_LTE,
                ProvisioningManager.PROVISIONING_VALUE_ENABLED);
        mImsStats.onImsRegistered(TRANSPORT_TYPE_WWAN);
        mImsStats.onImsCapabilitiesChanged(
                REGISTRATION_TECH_LTE, new MmTelCapabilities(CAPABILITY_TYPE_VOICE));

        verify(mServiceStateStats).onImsVoiceRegistrationChanged();

        mImsStats.incTimeMillis(2000L);
        mImsStats.onImsCapabilitiesChanged(
                REGISTRATION_TECH_NR, new MmTelCapabilities(CAPABILITY_TYPE_VOICE));

        // Atom with previous feature availability should be generated
        ArgumentCaptor<ImsRegistrationStats> captor =
                ArgumentCaptor.forClass(ImsRegistrationStats.class);
        verify(mPersistAtomsStorage).addImsRegistrationStats(captor.capture());
        ImsRegistrationStats stats = captor.getValue();
        assertEquals(CARRIER1_ID, stats.carrierId);
        assertEquals(0, stats.simSlotIndex);
        assertEquals(TelephonyManager.NETWORK_TYPE_LTE, stats.rat);
        assertEquals(2000L, stats.registeredMillis);
        assertEquals(2000L, stats.voiceCapableMillis);
        assertEquals(2000L, stats.voiceAvailableMillis);
        assertEquals(0L, stats.videoCapableMillis);
        assertEquals(0L, stats.videoAvailableMillis);
        assertEquals(0L, stats.utCapableMillis);
        assertEquals(0L, stats.utAvailableMillis);
        assertEquals(0L, stats.smsCapableMillis);
        assertEquals(0L, stats.smsAvailableMillis);
        verifyNoMoreInteractions(mPersistAtomsStorage);
        // ServiceStateStats should be notified
        verify(mServiceStateStats, times(2)).onImsVoiceRegistrationChanged();
    }

    @Test
    @SmallTest
    public void onImsCapabilitiesChanged_differentTechNoVoice() throws Exception {
        mImsStats.onSetFeatureResponse(
                CAPABILITY_TYPE_SMS,
                REGISTRATION_TECH_LTE,
                ProvisioningManager.PROVISIONING_VALUE_ENABLED);
        mImsStats.onImsRegistered(TRANSPORT_TYPE_WWAN);
        mImsStats.onImsCapabilitiesChanged(
                REGISTRATION_TECH_LTE, new MmTelCapabilities(CAPABILITY_TYPE_SMS));

        verify(mServiceStateStats, never()).onImsVoiceRegistrationChanged();

        mImsStats.incTimeMillis(2000L);
        mImsStats.onImsCapabilitiesChanged(
                REGISTRATION_TECH_NR, new MmTelCapabilities(CAPABILITY_TYPE_SMS));

        // Atom with previous feature availability should be generated
        ArgumentCaptor<ImsRegistrationStats> captor =
                ArgumentCaptor.forClass(ImsRegistrationStats.class);
        verify(mPersistAtomsStorage).addImsRegistrationStats(captor.capture());
        ImsRegistrationStats stats = captor.getValue();
        assertEquals(CARRIER1_ID, stats.carrierId);
        assertEquals(0, stats.simSlotIndex);
        assertEquals(TelephonyManager.NETWORK_TYPE_LTE, stats.rat);
        assertEquals(2000L, stats.registeredMillis);
        assertEquals(0L, stats.voiceCapableMillis);
        assertEquals(0L, stats.voiceAvailableMillis);
        assertEquals(0L, stats.videoCapableMillis);
        assertEquals(0L, stats.videoAvailableMillis);
        assertEquals(0L, stats.utCapableMillis);
        assertEquals(0L, stats.utAvailableMillis);
        assertEquals(2000L, stats.smsCapableMillis);
        assertEquals(2000L, stats.smsAvailableMillis);
        verifyNoMoreInteractions(mPersistAtomsStorage);
        // ServiceStateStats should not be notified
        verify(mServiceStateStats, never()).onImsVoiceRegistrationChanged();
    }

    @Test
@@ -722,4 +806,61 @@ public class ImsStatsTest extends TelephonyTest {
        assertEquals("Timeout", termination.extraMessage);
        verifyNoMoreInteractions(mPersistAtomsStorage);
    }

    @Test
    @SmallTest
    public void getImsVoiceRadioTech_noRegistration() throws Exception {
        // Do nothing

        assertEquals(TelephonyManager.NETWORK_TYPE_UNKNOWN, mImsStats.getImsVoiceRadioTech());
    }

    @Test
    @SmallTest
    public void getImsVoiceRadioTech_noVoiceRegistration() throws Exception {
        mImsStats.onImsRegistered(TRANSPORT_TYPE_WWAN);
        mImsStats.onImsCapabilitiesChanged(
                REGISTRATION_TECH_LTE, new MmTelCapabilities(CAPABILITY_TYPE_SMS));

        assertEquals(TelephonyManager.NETWORK_TYPE_UNKNOWN, mImsStats.getImsVoiceRadioTech());
    }

    @Test
    @SmallTest
    public void getImsVoiceRadioTech_cellularRegistration() throws Exception {
        mImsStats.onImsRegistered(TRANSPORT_TYPE_WWAN);
        mImsStats.onImsCapabilitiesChanged(
                REGISTRATION_TECH_LTE, new MmTelCapabilities(CAPABILITY_TYPE_VOICE));

        assertEquals(TelephonyManager.NETWORK_TYPE_LTE, mImsStats.getImsVoiceRadioTech());
    }

    @Test
    @SmallTest
    public void getImsVoiceRadioTech_wifiRegistration() throws Exception {
        mImsStats.onImsRegistered(TRANSPORT_TYPE_WLAN);
        mImsStats.onImsCapabilitiesChanged(
                REGISTRATION_TECH_IWLAN, new MmTelCapabilities(CAPABILITY_TYPE_VOICE));

        assertEquals(TelephonyManager.NETWORK_TYPE_IWLAN, mImsStats.getImsVoiceRadioTech());
    }

    @Test
    @SmallTest
    public void getImsVoiceRadioTech_unregistered() throws Exception {
        mImsStats.onImsRegistered(TRANSPORT_TYPE_WWAN);
        mImsStats.onImsCapabilitiesChanged(
                REGISTRATION_TECH_LTE, new MmTelCapabilities(CAPABILITY_TYPE_VOICE));
        mImsStats.onImsUnregistered(
                new ImsReasonInfo(ImsReasonInfo.CODE_REGISTRATION_ERROR, 999, "Timeout"));
        doReturn(
                        new NetworkRegistrationInfo.Builder()
                                .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_UMTS)
                                .build())
                .when(mServiceState)
                .getNetworkRegistrationInfo(DOMAIN_PS, TRANSPORT_TYPE_WWAN);


        assertEquals(TelephonyManager.NETWORK_TYPE_UNKNOWN, mImsStats.getImsVoiceRadioTech());
    }
}
+2 −3
Original line number Diff line number Diff line
@@ -192,7 +192,7 @@ public class ServiceStateStatsTest extends TelephonyTest {
        doReturn(TelephonyManager.NETWORK_TYPE_UNKNOWN).when(mServiceState).getVoiceNetworkType();
        doReturn(TelephonyManager.NETWORK_TYPE_IWLAN).when(mServiceState).getDataNetworkType();
        mockWwanPsRat(TelephonyManager.NETWORK_TYPE_UNKNOWN);
        doReturn(true).when(mImsPhone).isWifiCallingEnabled();
        doReturn(TelephonyManager.NETWORK_TYPE_IWLAN).when(mImsStats).getImsVoiceRadioTech();
        mServiceStateStats.onServiceStateChanged(mServiceState);

        mServiceStateStats.incTimeMillis(100L);
@@ -395,7 +395,7 @@ public class ServiceStateStatsTest extends TelephonyTest {
        mServiceStateStats.incTimeMillis(100L);
        // Voice RAT changes to IWLAN and data RAT stays in LTE according to WWAN PS RAT
        doReturn(TelephonyManager.NETWORK_TYPE_IWLAN).when(mServiceState).getDataNetworkType();
        doReturn(true).when(mImsPhone).isWifiCallingEnabled();
        doReturn(TelephonyManager.NETWORK_TYPE_IWLAN).when(mImsStats).getImsVoiceRadioTech();
        mServiceStateStats.onServiceStateChanged(mServiceState);
        mServiceStateStats.incTimeMillis(100L);

@@ -433,7 +433,6 @@ public class ServiceStateStatsTest extends TelephonyTest {
    public void update_iwlanButNotWifiCalling() throws Exception {
        // Using default service state for LTE as WWAN PS RAT
        doReturn(TelephonyManager.NETWORK_TYPE_IWLAN).when(mServiceState).getDataNetworkType();
        doReturn(false).when(mImsPhone).isWifiCallingEnabled();

        mServiceStateStats.onServiceStateChanged(mServiceState);

+2 −2
Original line number Diff line number Diff line
@@ -1907,7 +1907,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest {
    public void singleWifiCall_preferred() {
        setServiceStateWithWifiCalling(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
        doReturn(mImsPhone).when(mPhone).getImsPhone();
        doReturn(true).when(mImsPhone).isWifiCallingEnabled();
        doReturn(TelephonyManager.NETWORK_TYPE_IWLAN).when(mImsStats).getImsVoiceRadioTech();
        doReturn(true).when(mImsConnection0).isIncoming();
        doReturn(2000L).when(mImsConnection0).getCreateTime();
        doReturn(mImsCall0).when(mImsConnection0).getCall();
@@ -1955,7 +1955,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest {
    public void singleWifiCall_airPlaneMode() {
        setServiceStateWithWifiCalling(mServiceState, TelephonyManager.NETWORK_TYPE_UNKNOWN);
        doReturn(mImsPhone).when(mPhone).getImsPhone();
        doReturn(true).when(mImsPhone).isWifiCallingEnabled();
        doReturn(TelephonyManager.NETWORK_TYPE_IWLAN).when(mImsStats).getImsVoiceRadioTech();
        doReturn(true).when(mImsConnection0).isIncoming();
        doReturn(2000L).when(mImsConnection0).getCreateTime();
        doReturn(mImsCall0).when(mImsConnection0).getCall();