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

Commit bdaed78d authored by Naveen Kalla's avatar Naveen Kalla
Browse files

Collect telephony metrics for CS Calls.

Log Dial, Hangup and CS Call state changes in telephony.

Bug: 32885463
Test: Make circuit-switched calls on the pixel device and
check the logs. Run telephony unit tests
Change-Id: I0191f30a691bb0496600cba608387b06e7b3d6dd
parent deea0f36
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -1030,6 +1030,13 @@ message TelephonyCallSession {
      optional CallState state = 2;

      optional Type type = 3;

      // For possible values for a call end reason check
      // frameworks/base/telephony/java/android/telephony/DisconnectCause.java
      optional int32 call_end_reason = 4;

      // This field is true for Conference Calls
      optional bool is_multiparty = 5;
    }

    // Single Radio Voice Call Continuity(SRVCC) progress state
+49 −12
Original line number Diff line number Diff line
@@ -32,13 +32,12 @@ import android.telephony.CarrierConfigManager;
import android.telephony.CellLocation;
import android.telephony.DisconnectCause;
import android.telephony.PhoneNumberUtils;
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.telephony.cdma.CdmaCellLocation;
import android.telephony.gsm.GsmCellLocation;
import android.text.TextUtils;
import java.util.Iterator;
import android.telephony.Rlog;
import android.util.EventLog;

import com.android.internal.telephony.cdma.CdmaCallWaitingNotification;
@@ -46,8 +45,9 @@ import com.android.internal.telephony.metrics.TelephonyMetrics;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * {@hide}
@@ -90,6 +90,8 @@ public class GsmCdmaCallTracker extends CallTracker {

    public PhoneConstants.State mState = PhoneConstants.State.IDLE;

    private TelephonyMetrics mMetrics = TelephonyMetrics.getInstance();

    // Following member variables are for CDMA only
    private RegistrantList mCallWaitingRegistrants = new RegistrantList();
    private boolean mPendingCallInEcm;
@@ -305,6 +307,8 @@ public class GsmCdmaCallTracker extends CallTracker {
        mPendingMO = new GsmCdmaConnection(mPhone, checkForTestEmergencyNumber(dialString),
                this, mForegroundCall, isEmergencyCall);
        mHangupPendingMO = false;
        mMetrics.writeRilDial(mPhone.getPhoneId(), mPendingMO, clirMode, uusInfo);


        if ( mPendingMO.getAddress() == null || mPendingMO.getAddress().length() == 0
                || mPendingMO.getAddress().indexOf(PhoneNumberUtils.WILD) >= 0) {
@@ -725,7 +729,7 @@ public class GsmCdmaCallTracker extends CallTracker {
        }
        if (mState != oldState) {
            mPhone.notifyPhoneStateChanged();
            TelephonyMetrics.getInstance().writePhoneState(mPhone.getPhoneId(), mState);
            mMetrics.writePhoneState(mPhone.getPhoneId(), mState);
        }
    }

@@ -873,9 +877,6 @@ public class GsmCdmaCallTracker extends CallTracker {
                    // Connection missing in CLCC response that we were
                    // tracking.
                    mDroppedDuringPoll.add(conn);
                    // Dropped connections are removed from the CallTracker
                    // list but kept in the GsmCdmaCall list
                    mConnections[i] = null;
                } else {
                    // This case means the RIL has no more active call anymore and
                    // we need to clean up the foregroundCall and ringingCall.
@@ -902,12 +903,10 @@ public class GsmCdmaCallTracker extends CallTracker {
                    }
                    // If emergency call is not going through while dialing
                    checkAndEnableDataCallAfterEmergencyCallDropped();

                }
                // Dropped connections are removed from the CallTracker
                // list but kept in the Call list
                mConnections[i] = null;

                }
            } else if (conn != null && dc != null && !conn.compareTo(dc) && isPhoneTypeGsm()) {
                // Connection in CLCC response does not match what
                // we were tracking. Assume dropped call and new call
@@ -997,6 +996,7 @@ public class GsmCdmaCallTracker extends CallTracker {
        // clear the "local hangup" and "missed/rejected call"
        // cases from the "dropped during poll" list
        // These cases need no "last call fail" reason
        ArrayList<GsmCdmaConnection> locallyDisconnectedConnections = new ArrayList<>();
        for (int i = mDroppedDuringPoll.size() - 1; i >= 0 ; i--) {
            GsmCdmaConnection conn = mDroppedDuringPoll.get(i);
            //CDMA
@@ -1018,11 +1018,13 @@ public class GsmCdmaCallTracker extends CallTracker {
                mDroppedDuringPoll.remove(i);
                hasAnyCallDisconnected |= conn.onDisconnect(cause);
                wasDisconnected = true;
                locallyDisconnectedConnections.add(conn);
            } else if (conn.mCause == DisconnectCause.LOCAL
                    || conn.mCause == DisconnectCause.INVALID_NUMBER) {
                mDroppedDuringPoll.remove(i);
                hasAnyCallDisconnected |= conn.onDisconnect(conn.mCause);
                wasDisconnected = true;
                locallyDisconnectedConnections.add(conn);
            }

            if (!isPhoneTypeGsm() && wasDisconnected && unknownConnectionAppeared
@@ -1031,6 +1033,9 @@ public class GsmCdmaCallTracker extends CallTracker {
                newUnknownConnectionCdma = null;
            }
        }
        if (locallyDisconnectedConnections.size() > 0) {
            mMetrics.writeRilCallList(mPhone.getPhoneId(), locallyDisconnectedConnections);
        }

        /* Disconnect any pending Handover connections */
        for (Iterator<Connection> it = mHandoverConnections.iterator();
@@ -1043,6 +1048,7 @@ public class GsmCdmaCallTracker extends CallTracker {
            } else {
                hoConnection.onDisconnect(DisconnectCause.NOT_VALID);
            }
            // TODO: Do we need to update these hoConnections in Metrics ?
            it.remove();
        }

@@ -1081,6 +1087,7 @@ public class GsmCdmaCallTracker extends CallTracker {

        if (hasNonHangupStateChanged || newRinging != null || hasAnyCallDisconnected) {
            mPhone.notifyPreciseCallStateChanged();
            updateMetrics(mConnections);
        }

        // If all handover connections are mapped during this poll process clean it up
@@ -1093,6 +1100,14 @@ public class GsmCdmaCallTracker extends CallTracker {
        //dumpState();
    }

    private void updateMetrics(GsmCdmaConnection[] connections) {
        ArrayList<GsmCdmaConnection> activeConnections = new ArrayList<>();
        for (GsmCdmaConnection conn : connections) {
            if (conn != null) activeConnections.add(conn);
        }
        mMetrics.writeRilCallList(mPhone.getPhoneId(), activeConnections);
    }

    private void handleRadioNotAvailable() {
        // handlePollCalls will clear out its
        // call list when it gets the CommandException
@@ -1163,6 +1178,7 @@ public class GsmCdmaCallTracker extends CallTracker {
            return;
        } else {
            try {
                mMetrics.writeRilHangup(mPhone.getPhoneId(), conn, conn.getGsmCdmaIndex());
                mCi.hangupConnection (conn.getGsmCdmaIndex(), obtainCompleteMessage());
            } catch (CallStateException ex) {
                // Ignore "connection not found"
@@ -1211,6 +1227,7 @@ public class GsmCdmaCallTracker extends CallTracker {

        if (call == mRingingCall) {
            if (Phone.DEBUG_PHONE) log("(ringing) hangup waiting or background");
            logHangupEvent(call);
            mCi.hangupWaitingOrBackground(obtainCompleteMessage());
        } else if (call == mForegroundCall) {
            if (call.isDialingOrAlerting()) {
@@ -1224,6 +1241,7 @@ public class GsmCdmaCallTracker extends CallTracker {
                log("hangup all conns in active/background call, without affecting ringing call");
                hangupAllConnections(call);
            } else {
                logHangupEvent(call);
                hangupForegroundResumeBackground();
            }
        } else if (call == mBackgroundCall) {
@@ -1244,8 +1262,24 @@ public class GsmCdmaCallTracker extends CallTracker {
        mPhone.notifyPreciseCallStateChanged();
    }

    private void logHangupEvent(GsmCdmaCall call) {
        int count = call.mConnections.size();
        for (int i = 0; i < count; i++) {
            GsmCdmaConnection cn = (GsmCdmaConnection) call.mConnections.get(i);
            int call_index;
            try {
                call_index = cn.getGsmCdmaIndex();
            } catch (CallStateException ex) {
                call_index = -1;
            }
            mMetrics.writeRilHangup(mPhone.getPhoneId(), cn, call_index);
        }
        if (VDBG) Rlog.v(LOG_TAG, "logHangupEvent logged " + count + " Connections ");
    }

    public void hangupWaitingOrBackground() {
        if (Phone.DEBUG_PHONE) log("hangupWaitingOrBackground");
        logHangupEvent(mBackgroundCall);
        mCi.hangupWaitingOrBackground(obtainCompleteMessage());
    }

@@ -1260,6 +1294,7 @@ public class GsmCdmaCallTracker extends CallTracker {
        for (int i = 0; i < count; i++) {
            GsmCdmaConnection cn = (GsmCdmaConnection)call.mConnections.get(i);
            if (!cn.mDisconnected && cn.getGsmCdmaIndex() == index) {
                mMetrics.writeRilHangup(mPhone.getPhoneId(), cn, cn.getGsmCdmaIndex());
                mCi.hangupConnection(index, obtainCompleteMessage());
                return;
            }
@@ -1274,6 +1309,7 @@ public class GsmCdmaCallTracker extends CallTracker {
            for (int i = 0; i < count; i++) {
                GsmCdmaConnection cn = (GsmCdmaConnection)call.mConnections.get(i);
                if (!cn.mDisconnected) {
                    mMetrics.writeRilHangup(mPhone.getPhoneId(), cn, cn.getGsmCdmaIndex());
                    mCi.hangupConnection(cn.getGsmCdmaIndex(), obtainCompleteMessage());
                }
            }
@@ -1428,6 +1464,7 @@ public class GsmCdmaCallTracker extends CallTracker {
                updatePhoneState();

                mPhone.notifyPreciseCallStateChanged();
                mMetrics.writeRilCallList(mPhone.getPhoneId(), mDroppedDuringPoll);
                mDroppedDuringPoll.clear();
            break;

+0 −12
Original line number Diff line number Diff line
@@ -56,13 +56,11 @@ import android.telephony.CellInfo;
import android.telephony.ClientRequestStats;
import android.telephony.ModemActivityInfo;
import android.telephony.NeighboringCellInfo;
import android.telephony.PcoData;
import android.telephony.PhoneNumberUtils;
import android.telephony.RadioAccessFamily;
import android.telephony.Rlog;
import android.telephony.SignalStrength;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyHistogram;
import android.telephony.TelephonyManager;
@@ -70,14 +68,12 @@ import android.text.TextUtils;
import android.util.SparseArray;
import android.view.Display;

import com.android.internal.telephony.cdma.CdmaCallWaitingNotification;
import com.android.internal.telephony.cdma.CdmaInformationRecords;
import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
import com.android.internal.telephony.dataconnection.DataCallResponse;
import com.android.internal.telephony.dataconnection.DataProfile;
import com.android.internal.telephony.dataconnection.DcFailCause;
import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
import com.android.internal.telephony.gsm.SsData;
import com.android.internal.telephony.gsm.SuppServiceNotification;
import com.android.internal.telephony.metrics.TelephonyMetrics;
import com.android.internal.telephony.nano.TelephonyProto.SmsSession;
@@ -1209,8 +1205,6 @@ public final class RIL extends BaseCommands implements CommandsInterface {
            rr.onError(RADIO_NOT_AVAILABLE, null);
            rr.release();
        }

        mMetrics.writeRilDial(mInstanceId, rr.mSerial, clirMode, uusInfo);
    }

    public void setUiccSubscription(int slotId, int appIndex, int subId,
@@ -1329,8 +1323,6 @@ public final class RIL extends BaseCommands implements CommandsInterface {
        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " " +
                gsmIndex);

        mMetrics.writeRilHangup(mInstanceId, rr.mSerial, gsmIndex);

        rr.mParcel.writeInt(1);
        rr.mParcel.writeInt(gsmIndex);

@@ -1345,8 +1337,6 @@ public final class RIL extends BaseCommands implements CommandsInterface {

        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));

        mMetrics.writeRilHangup(mInstanceId, rr.mSerial, -1);

        send(rr);
    }

@@ -1359,8 +1349,6 @@ public final class RIL extends BaseCommands implements CommandsInterface {
                                        result, mRILDefaultWorkSource);
        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));

        mMetrics.writeRilHangup(mInstanceId, rr.mSerial, -1);

        send(rr);
    }

+7 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import com.android.internal.telephony.nano.TelephonyProto.ImsConnectionState;
import com.android.internal.telephony.nano.TelephonyProto.ImsReasonInfo;
import com.android.internal.telephony.nano.TelephonyProto.RilDataCall;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyCallSession;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyCallSession.Event.RilCall;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyServiceState;
import com.android.internal.telephony.nano.TelephonyProto.TelephonySettings;

@@ -124,4 +125,9 @@ public class CallSessionEventBuilder {
        mEvent.nitzTimestampMillis = timestamp;
        return this;
    }

    public CallSessionEventBuilder setRilCalls(RilCall[] rilCalls) {
        mEvent.calls = rilCalls;
        return this;
    }
}
+112 −20
Original line number Diff line number Diff line
@@ -47,16 +47,23 @@ import android.util.SparseArray;
import com.android.ims.ImsConfig;
import com.android.ims.ImsReasonInfo;
import com.android.ims.internal.ImsCallSession;
import com.android.internal.telephony.GsmCdmaConnection;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.RIL;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.SmsResponse;
import com.android.internal.telephony.UUSInfo;
import com.android.internal.telephony.dataconnection.DataCallResponse;
import com.android.internal.telephony.imsphone.ImsPhoneCall;
import com.android.internal.telephony.nano.TelephonyProto;
import com.android.internal.telephony.nano.TelephonyProto.ImsCapabilities;
import com.android.internal.telephony.nano.TelephonyProto.ImsConnectionState;
import com.android.internal.telephony.nano.TelephonyProto.RilDataCall;
import com.android.internal.telephony.nano.TelephonyProto.SmsSession;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyCallSession;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyCallSession.Event.CallState;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyCallSession.Event.RilCall;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyCallSession.Event.RilCall.Type;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.ModemRestart;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.RilDeactivateDataCall;
@@ -68,9 +75,6 @@ import com.android.internal.telephony.nano.TelephonyProto.TelephonyLog;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyServiceState;
import com.android.internal.telephony.nano.TelephonyProto.TelephonySettings;
import com.android.internal.telephony.nano.TelephonyProto.TimeInterval;
import com.android.internal.telephony.UUSInfo;
import com.android.internal.telephony.dataconnection.DataCallResponse;
import com.android.internal.telephony.imsphone.ImsPhoneCall;
import com.android.internal.util.IndentingPrintWriter;

import java.io.FileDescriptor;
@@ -1057,23 +1061,107 @@ public class TelephonyMetrics {
        addTelephonyEvent(new TelephonyEventBuilder(phoneId).setDataCalls(dataCalls).build());
    }

    /**
     * Write CS call list event
     *
     * @param phoneId    Phone id
     * @param connections Array of GsmCdmaConnection objects
     */
    public void writeRilCallList(int phoneId, ArrayList<GsmCdmaConnection> connections) {
        if (VDBG) {
            Rlog.v(TAG, "Logging CallList Changed Connections Size = " + connections.size());
        }
        InProgressCallSession callSession = startNewCallSessionIfNeeded(phoneId);
        if (callSession == null) {
            Rlog.e(TAG, "writeRilCallList: Call session is missing");
        } else {
            RilCall[] calls = convertConnectionsToRilCalls(connections);
            callSession.addEvent(
                    new CallSessionEventBuilder(
                            TelephonyCallSession.Event.Type.RIL_CALL_LIST_CHANGED)
                            .setRilCalls(calls)
            );
            if (VDBG)  Rlog.v(TAG, "Logged Call list changed");
        }
    }

    private RilCall[] convertConnectionsToRilCalls(ArrayList<GsmCdmaConnection> mConnections) {
        RilCall[] calls = new RilCall[mConnections.size()];
        for (int i = 0; i < mConnections.size(); i++) {
            calls[i] = new RilCall();
            calls[i].index = i;
            convertConnectionToRilCall(mConnections.get(i), calls[i]);
        }
        return calls;
    }

    private void convertConnectionToRilCall(GsmCdmaConnection conn, RilCall call) {
        if (conn.isIncoming()) {
            call.type = Type.MT;
        } else {
            call.type = Type.MO;
        }
        switch (conn.getState()) {
            case IDLE:
                call.state = CallState.CALL_IDLE;
                break;
            case ACTIVE:
                call.state = CallState.CALL_ACTIVE;
                break;
            case HOLDING:
                call.state = CallState.CALL_HOLDING;
                break;
            case DIALING:
                call.state = CallState.CALL_DIALING;
                break;
            case ALERTING:
                call.state = CallState.CALL_ALERTING;
                break;
            case INCOMING:
                call.state = CallState.CALL_INCOMING;
                break;
            case WAITING:
                call.state = CallState.CALL_WAITING;
                break;
            case DISCONNECTED:
                call.state = CallState.CALL_DISCONNECTED;
                break;
            case DISCONNECTING:
                call.state = CallState.CALL_DISCONNECTING;
                break;
            default:
                call.state = CallState.CALL_UNKNOWN;
                break;
        }
        call.callEndReason = conn.getDisconnectCause();
        call.isMultiparty = conn.isMultiparty();
    }

    /**
     * Write dial event
     *
     * @param phoneId Phone id
     * @param rilSerial RIL request serial number
     * @param conn Connection object created to track this call
     * @param clirMode CLIR (Calling Line Identification Restriction) mode
     * @param uusInfo User-to-User signaling Info
     */
    public void writeRilDial(int phoneId, int rilSerial, int clirMode, UUSInfo uusInfo) {
    public void writeRilDial(int phoneId, GsmCdmaConnection conn, int clirMode, UUSInfo uusInfo) {

        InProgressCallSession callSession = startNewCallSessionIfNeeded(phoneId);

        if (VDBG) Rlog.v(TAG, "Logging Dial Connection = " + conn);
        if (callSession == null) {
            Rlog.e(TAG, "writeRilDial: Call session is missing");
        } else {
            RilCall[] calls = new RilCall[1];
            calls[0] = new RilCall();
            calls[0].index = -1;
            convertConnectionToRilCall(conn, calls[0]);
            callSession.addEvent(callSession.startElapsedTimeMs,
                    new CallSessionEventBuilder(TelephonyCallSession.Event.Type.RIL_REQUEST)
                            .setRilRequest(TelephonyCallSession.Event.RilRequest.RIL_REQUEST_DIAL)
                        .setRilRequestId(rilSerial)
        );
                            .setRilCalls(calls));
            if (VDBG) Rlog.v(TAG, "Logged Dial event");
        }
    }

    /**
@@ -1093,19 +1181,23 @@ public class TelephonyMetrics {
     * Write call hangup event
     *
     * @param phoneId Phone id
     * @param rilSerial RIL request serial number
     * @param conn Connection object associated with the call that is being hung-up
     * @param callId Call id
     */
    public void writeRilHangup(int phoneId, int rilSerial, int callId) {
    public void writeRilHangup(int phoneId, GsmCdmaConnection conn, int callId) {
        InProgressCallSession callSession = mInProgressCallSessions.get(phoneId);
        if (callSession == null) {
            Rlog.e(TAG, "Call session is missing");
            Rlog.e(TAG, "writeRilHangup: Call session is missing");
        } else {
            RilCall[] calls = new RilCall[1];
            calls[0] = new RilCall();
            calls[0].index = callId;
            convertConnectionToRilCall(conn, calls[0]);
            callSession.addEvent(
                    new CallSessionEventBuilder(TelephonyCallSession.Event.Type.RIL_REQUEST)
                            .setRilRequest(TelephonyCallSession.Event.RilRequest.RIL_REQUEST_HANGUP)
                            .setRilRequestId(rilSerial)
                            .setCallIndex(callId));
                            .setRilCalls(calls));
            if (VDBG) Rlog.v(TAG, "Logged Hangup event");
        }
    }

@@ -1118,7 +1210,7 @@ public class TelephonyMetrics {
    public void writeRilAnswer(int phoneId, int rilSerial) {
        InProgressCallSession callSession = mInProgressCallSessions.get(phoneId);
        if (callSession == null) {
            Rlog.e(TAG, "Call session is missing");
            Rlog.e(TAG, "writeRilAnswer: Call session is missing");
        } else {
            callSession.addEvent(
                    new CallSessionEventBuilder(TelephonyCallSession.Event.Type.RIL_REQUEST)
@@ -1136,7 +1228,7 @@ public class TelephonyMetrics {
    public void writeRilSrvcc(int phoneId, int rilSrvccState) {
        InProgressCallSession callSession =  mInProgressCallSessions.get(phoneId);
        if (callSession == null) {
            Rlog.e(TAG, "Call session is missing");
            Rlog.e(TAG, "writeRilSrvcc: Call session is missing");
        } else {
            callSession.addEvent(
                    new CallSessionEventBuilder(TelephonyCallSession.Event.Type.RIL_CALL_SRVCC)
@@ -1226,7 +1318,7 @@ public class TelephonyMetrics {
                                              int rilRequest) {
        InProgressCallSession callSession = mInProgressCallSessions.get(phoneId);
        if (callSession == null) {
            Rlog.e(TAG, "Call session is missing");
            Rlog.e(TAG, "writeOnCallSolicitedResponse: Call session is missing");
        } else {
            callSession.addEvent(new CallSessionEventBuilder(
                    TelephonyCallSession.Event.Type.RIL_RESPONSE)
@@ -1341,7 +1433,7 @@ public class TelephonyMetrics {

        InProgressCallSession callSession = mInProgressCallSessions.get(phoneId);
        if (callSession == null) {
            Rlog.e(TAG, "Call session is missing");
            Rlog.e(TAG, "writePhoneState: Call session is missing");
        } else {
            if (state == TelephonyCallSession.Event.PhoneState.STATE_IDLE) {
                finishCallSession(callSession);
Loading