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

Commit 80896de9 authored by Aswin Sankar's avatar Aswin Sankar
Browse files

VoiceCallSessionStats captures Cross-SIM Calling

- Adds boolean fields for "is_iwlan_cross_sim_*" that shadow the
  "rat_at_start", "rat_at_end" and "rat_at_connected" fields and are
applicable when the NetworkType is IWLAN.
- Separate booleans are necessary since NetworkType does not have a
  dedicated field for cross-SIM calling.

Bug: 294240210
Test: Updated VoiceCallSessionStatsTest, on device testing with go/telephony-ww-local-testing
Change-Id: I2c94de91d8187d6c077c66f3a7c7c092c63a58f9
Merged-In: I2c94de91d8187d6c077c66f3a7c7c092c63a58f9
parent 041adf1a
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -277,6 +277,9 @@ message VoiceCallSession {
    optional int32 fold_state = 34;
    optional int64 rat_switch_count_after_connected = 35;
    optional bool handover_in_progress = 36;
    optional bool is_iwlan_cross_sim_at_start = 37;
    optional bool is_iwlan_cross_sim_at_end = 38;
    optional bool is_iwlan_cross_sim_at_connected = 39;

    // Internal use only
    optional int64 setup_begin_millis = 10001;
+4 −1
Original line number Diff line number Diff line
@@ -979,7 +979,10 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback {
                session.lastKnownRat,
                session.foldState,
                session.ratSwitchCountAfterConnected,
                session.handoverInProgress);
                session.handoverInProgress,
                session.isIwlanCrossSimAtStart,
                session.isIwlanCrossSimAtEnd,
                session.isIwlanCrossSimAtConnected);
    }

    private static StatsEvent buildStatsEvent(IncomingSms sms) {
+25 −1
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ImsStreamMediaProfile;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.util.LongSparseArray;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -469,6 +470,11 @@ public class VoiceCallSessionStats {
        proto.videoEnabled = videoState != VideoProfile.STATE_AUDIO_ONLY ? true : false;
        proto.handoverInProgress = isHandoverInProgress(bearer, proto.isEmergency);

        boolean isCrossSimCall = isCrossSimCall(conn);
        proto.isIwlanCrossSimAtStart = isCrossSimCall;
        proto.isIwlanCrossSimAtEnd = isCrossSimCall;
        proto.isIwlanCrossSimAtConnected = isCrossSimCall;

        // internal fields for tracking
        if (getDirection(conn) == VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MT) {
            // MT call setup hasn't begun hence set to 0
@@ -594,7 +600,9 @@ public class VoiceCallSessionStats {
            proto.setupFailed = false;
            // Track RAT when voice call is connected.
            ServiceState serviceState = getServiceState();
            proto.ratAtConnected = getVoiceRatWithVoNRFix(mPhone, serviceState, proto.bearerAtEnd);
            @NetworkType int rat = getVoiceRatWithVoNRFix(mPhone, serviceState, proto.bearerAtEnd);
            proto.ratAtConnected = rat;
            proto.isIwlanCrossSimAtConnected = isCrossSimCall(conn);
            // Reset list of codecs with the last codec at the present time. In this way, we
            // track codec quality only after call is connected and not while ringing.
            resetCodecList(conn);
@@ -631,6 +639,7 @@ public class VoiceCallSessionStats {
                proto.lastKnownRat = rat;
            }
        }
        proto.isIwlanCrossSimAtEnd = isCrossSimCall(mPhone);
    }

    private void finishImsCall(int id, ImsReasonInfo reasonInfo, long durationMillis) {
@@ -878,6 +887,21 @@ public class VoiceCallSessionStats {
        return conn == null ? 0 : (int) conn.getCreateTime();
    }

    private boolean isCrossSimCall(Connection conn) {
        if (conn instanceof ImsPhoneConnection) {
            return ((ImsPhoneConnection) conn).isCrossSimCall();
        }
        return false;
    }

    private boolean isCrossSimCall(Phone phone) {
        if (phone.getImsPhone() != null) {
            return phone.getImsPhone().getImsRegistrationTech()
                    == ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM;
        }
        return false;
    }

    @VisibleForTesting
    protected long getTimeMillis() {
        return SystemClock.elapsedRealtime();
+78 −1
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ImsStreamMediaProfile;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.test.suitebuilder.annotation.SmallTest;

import com.android.internal.telephony.Call;
@@ -190,6 +191,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest {

        doReturn(PhoneConstants.PHONE_TYPE_IMS).when(mImsConnection0).getPhoneType();
        doReturn(false).when(mImsConnection0).isEmergencyCall();
        doReturn(false).when(mImsConnection0).isCrossSimCall();
        doReturn(PhoneConstants.PHONE_TYPE_IMS).when(mImsConnection1).getPhoneType();
        doReturn(false).when(mImsConnection1).isEmergencyCall();
        doReturn(PhoneConstants.PHONE_TYPE_GSM).when(mGsmConnection0).getPhoneType();
@@ -197,6 +199,9 @@ public class VoiceCallSessionStatsTest extends TelephonyTest {
        doReturn(PhoneConstants.PHONE_TYPE_GSM).when(mGsmConnection1).getPhoneType();
        doReturn(false).when(mGsmConnection1).isEmergencyCall();

        doReturn(ImsRegistrationImplBase.REGISTRATION_TECH_LTE).when(mImsPhone)
                .getImsRegistrationTech();

        if (Looper.myLooper() == null) {
            Looper.prepare();
        }
@@ -235,7 +240,6 @@ public class VoiceCallSessionStatsTest extends TelephonyTest {
                        ImsReasonInfo.CODE_REMOTE_CALL_DECLINE);
        expectedCall.setupDurationMillis = 200;
        expectedCall.setupFailed = true;
        expectedCall.ratAtConnected = TelephonyManager.NETWORK_TYPE_UNKNOWN;
        expectedCall.codecBitmask = 1L << AudioCodec.AUDIO_CODEC_EVS_SWB;
        expectedCall.mainCodecQuality =
                VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_SUPER_WIDEBAND;
@@ -1511,6 +1515,75 @@ public class VoiceCallSessionStatsTest extends TelephonyTest {
                ratUsage.get());
    }

    @Test
    @SmallTest
    public void singleCrossSimCall_moAccepted() {
        setServiceStateWithWifiCalling(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
        doReturn(mImsPhone).when(mPhone).getImsPhone();
        doReturn(ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM).when(mImsPhone)
                .getImsRegistrationTech();
        doReturn(TelephonyManager.NETWORK_TYPE_IWLAN).when(mImsStats).getImsVoiceRadioTech();
        doReturn(false).when(mImsConnection0).isIncoming();
        doReturn(true).when(mImsConnection0).isCrossSimCall();
        doReturn(2000L).when(mImsConnection0).getCreateTime();
        doReturn(1000L).when(mImsConnection0).getDurationMillis();
        doReturn(mImsCall0).when(mImsConnection0).getCall();
        doReturn(new ArrayList(List.of(mImsConnection0))).when(mImsCall0).getConnections();
        VoiceCallSession expectedCall =
                makeSlot0CallProto(
                        VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS,
                        VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MO,
                        TelephonyManager.NETWORK_TYPE_IWLAN,
                        ImsReasonInfo.CODE_USER_TERMINATED_BY_REMOTE);
        expectedCall.isIwlanCrossSimAtStart = true;
        expectedCall.isIwlanCrossSimAtEnd = true;
        expectedCall.isIwlanCrossSimAtConnected = true;

        expectedCall.bandAtEnd = 0; // not configured for IWLAN
        expectedCall.setupDurationMillis = 200;
        expectedCall.setupFailed = false;
        expectedCall.codecBitmask = 1L << AudioCodec.AUDIO_CODEC_EVS_SWB;
        expectedCall.mainCodecQuality =
                VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_SUPER_WIDEBAND;
        expectedCall.disconnectExtraMessage = "normal call clearing";
        expectedCall.callDuration =
                VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_ONE_MINUTE;
        VoiceCallRatUsage expectedRatUsage =
                makeRatUsageProto(
                        CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_IWLAN, 2000L, 100000L, 1L);
        final AtomicReference<VoiceCallRatUsage[]> ratUsage = setupRatUsageCapture();

        mVoiceCallSessionStats0.setTimeMillis(2000L);
        doReturn(Call.State.DIALING).when(mImsCall0).getState();
        doReturn(Call.State.DIALING).when(mImsConnection0).getState();
        mVoiceCallSessionStats0.onImsDial(mImsConnection0);
        mVoiceCallSessionStats0.setTimeMillis(2100L);
        mVoiceCallSessionStats0.onAudioCodecChanged(
                mImsConnection0, ImsStreamMediaProfile.AUDIO_QUALITY_EVS_SWB);
        mVoiceCallSessionStats0.setTimeMillis(2200L);
        doReturn(Call.State.ALERTING).when(mImsCall0).getState();
        doReturn(Call.State.ALERTING).when(mImsConnection0).getState();
        mVoiceCallSessionStats0.onCallStateChanged(mImsCall0);
        mVoiceCallSessionStats0.setTimeMillis(12000L);
        doReturn(Call.State.ACTIVE).when(mImsCall0).getState();
        doReturn(Call.State.ACTIVE).when(mImsConnection0).getState();
        mVoiceCallSessionStats0.onCallStateChanged(mImsCall0);
        mVoiceCallSessionStats0.setTimeMillis(100000L);
        mVoiceCallSessionStats0.onImsCallTerminated(
                mImsConnection0,
                new ImsReasonInfo(
                        ImsReasonInfo.CODE_USER_TERMINATED_BY_REMOTE, 0, "normal call clearing"));

        ArgumentCaptor<VoiceCallSession> callCaptor =
                ArgumentCaptor.forClass(VoiceCallSession.class);
        verify(mPersistAtomsStorage, times(1)).addVoiceCallSession(callCaptor.capture());
        verify(mPersistAtomsStorage, times(1)).addVoiceCallRatUsage(any());
        verifyNoMoreInteractions(mPersistAtomsStorage);
        assertProtoEquals(expectedCall, callCaptor.getValue());
        assertThat(ratUsage.get()).hasLength(1);
        assertProtoEquals(expectedRatUsage, ratUsage.get()[0]);
    }

    @Test
    @SmallTest
    public void singleCsCall_moRejected() {
@@ -2512,6 +2585,8 @@ public class VoiceCallSessionStatsTest extends TelephonyTest {
    public void singleWifiCall_preferred() {
        setServiceStateWithWifiCalling(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
        doReturn(mImsPhone).when(mPhone).getImsPhone();
        doReturn(ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN).when(mImsPhone)
                .getImsRegistrationTech();
        doReturn(TelephonyManager.NETWORK_TYPE_IWLAN).when(mImsStats).getImsVoiceRadioTech();
        doReturn(true).when(mImsConnection0).isIncoming();
        doReturn(2000L).when(mImsConnection0).getCreateTime();
@@ -2560,6 +2635,8 @@ public class VoiceCallSessionStatsTest extends TelephonyTest {
    public void singleWifiCall_airPlaneMode() {
        setServiceStateWithWifiCalling(mServiceState, TelephonyManager.NETWORK_TYPE_UNKNOWN);
        doReturn(mImsPhone).when(mPhone).getImsPhone();
        doReturn(ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN).when(mImsPhone)
                .getImsRegistrationTech();
        doReturn(TelephonyManager.NETWORK_TYPE_IWLAN).when(mImsStats).getImsVoiceRadioTech();
        doReturn(true).when(mImsConnection0).isIncoming();
        doReturn(2000L).when(mImsConnection0).getCreateTime();