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

Commit 28183f8d authored by Ling Ma's avatar Ling Ma Committed by Android (Google) Code Review
Browse files

Merge "Add handover failure cause to data call session" into tm-dev

parents fafd76b8 088f3ed9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -284,6 +284,7 @@ message DataCallSession {
    optional int64 duration_minutes = 17;
    optional bool ongoing = 18;
    optional int32 band_at_end = 19;
    repeated int32 handover_failure_causes = 20;
}

message CellularServiceState {
+1 −0
Original line number Diff line number Diff line
@@ -2851,6 +2851,7 @@ public class DataNetwork extends StateMachine {
            mDataNetworkCallback.invokeFromExecutor(
                    () -> mDataNetworkCallback.onHandoverFailed(DataNetwork.this,
                            mFailCause, retry, handoverFailureMode));
            mDataCallSessionStats.onHandoverFailure(mFailCause);
        }

        // No matter handover succeeded or not, transit back to connected state.
+46 −13
Original line number Diff line number Diff line
@@ -44,11 +44,13 @@ import com.android.internal.telephony.SubscriptionController;
import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession;
import com.android.telephony.Rlog;

import java.util.Arrays;
import java.util.Random;

/** Collects data call change events per DataConnection for the pulled atom. */
public class DataCallSessionStats {
    private static final String TAG = DataCallSessionStats.class.getSimpleName();
    private static final int SIZE_LIMIT_HANDOVER_FAILURE_CAUSES = 15;

    private final Phone mPhone;
    private long mStartTime;
@@ -112,12 +114,8 @@ public class DataCallSessionStats {
                    (int) Math.min(response.getRetryDurationMillis(), Integer.MAX_VALUE);
            // If setup has failed, then store the atom
            if (failureCause != DataFailCause.NONE) {
                mDataCallSession.oosAtEnd = getIsOos();
                mDataCallSession.setupFailed = true;
                mDataCallSession.ongoing = false;
                PhoneFactory.getMetricsCollector().unregisterOngoingDataCallStat(this);
                mAtomsStorage.addDataCallSession(mDataCallSession);
                mDataCallSession = null;
                endDataCallSession();
            }
        }
    }
@@ -168,14 +166,28 @@ public class DataCallSessionStats {
            return;
        }
        mDataCallSession.failureCause = failureCause;
        mDataCallSession.oosAtEnd = getIsOos();
        mDataCallSession.ongoing = false;
        mDataCallSession.durationMinutes = convertMillisToMinutes(getTimeMillis() - mStartTime);
        // store for the data call list event, after DataCall is disconnected and entered into
        // inactive mode
        PhoneFactory.getMetricsCollector().unregisterOngoingDataCallStat(this);
        mAtomsStorage.addDataCallSession(mDataCallSession);
        mDataCallSession = null;
        endDataCallSession();
    }

    /**
     * Updates the atom when a handover fails. Note we only record distinct failure causes, as in
     * most cases retry failures are due to the same cause.
     *
     * @param failureCause failure cause as per android.telephony.DataFailCause
     */
    public synchronized void onHandoverFailure(@DataFailureCause int failureCause) {
        if (mDataCallSession != null
                && mDataCallSession.handoverFailureCauses.length
                < SIZE_LIMIT_HANDOVER_FAILURE_CAUSES) {
            int[] failureCauses = mDataCallSession.handoverFailureCauses;
            for (int cause : failureCauses) {
                if (failureCause == cause) return;
            }
            mDataCallSession.handoverFailureCauses = Arrays.copyOf(
                    failureCauses, failureCauses.length + 1);
            mDataCallSession.handoverFailureCauses[failureCauses.length] = failureCause;
        }
    }

    /**
@@ -199,7 +211,13 @@ public class DataCallSessionStats {
        }
    }

    /** Add the on-going data call segment to the atom storage. */
    /**
     * Take a snapshot of the on-going data call segment to add to the atom storage.
     *
     * Note the following fields are reset after the snapshot:
     * - rat switch count
     * - handover failure causes
     */
    public synchronized void conclude() {
        if (mDataCallSession != null) {
            DataCallSession call = copyOf(mDataCallSession);
@@ -207,10 +225,22 @@ public class DataCallSessionStats {
            call.durationMinutes = convertMillisToMinutes(nowMillis - mStartTime);
            mStartTime = nowMillis;
            mDataCallSession.ratSwitchCount = 0L;
            mDataCallSession.handoverFailureCauses = new int[0];
            mAtomsStorage.addDataCallSession(call);
        }
    }

    /** Put the current data call to an end after being uploaded to AtomStorage. */
    private void endDataCallSession() {
        mDataCallSession.oosAtEnd = getIsOos();
        mDataCallSession.ongoing = false;
        // store for the data call list event, after DataCall is disconnected and entered into
        // inactive mode
        PhoneFactory.getMetricsCollector().unregisterOngoingDataCallStat(this);
        mAtomsStorage.addDataCallSession(mDataCallSession);
        mDataCallSession = null;
    }

    private static long convertMillisToMinutes(long millis) {
        return Math.round(millis / 60000.0);
    }
@@ -235,6 +265,8 @@ public class DataCallSessionStats {
        copy.durationMinutes = call.durationMinutes;
        copy.ongoing = call.ongoing;
        copy.bandAtEnd = call.bandAtEnd;
        copy.handoverFailureCauses = Arrays.copyOf(call.handoverFailureCauses,
                call.handoverFailureCauses.length);
        return copy;
    }

@@ -257,6 +289,7 @@ public class DataCallSessionStats {
        proto.deactivateReason = DATA_CALL_SESSION__DEACTIVATE_REASON__DEACTIVATE_REASON_UNKNOWN;
        proto.durationMinutes = 0;
        proto.ongoing = true;
        proto.handoverFailureCauses = new int[0];
        return proto;
    }

+2 −1
Original line number Diff line number Diff line
@@ -811,7 +811,8 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback {
                dataCallSession.deactivateReason,
                round(dataCallSession.durationMinutes, DURATION_BUCKET_MILLIS / MINUTE_IN_MILLIS),
                dataCallSession.ongoing,
                dataCallSession.bandAtEnd);
                dataCallSession.bandAtEnd,
                dataCallSession.handoverFailureCauses);
    }

    private static StatsEvent buildStatsEvent(ImsRegistrationStats stats) {
+4 −0
Original line number Diff line number Diff line
@@ -678,6 +678,10 @@ public class PersistAtomsStorage {
            DataCallSession[] previousDataCallSession = mAtoms.dataCallSession;
            mAtoms.dataCallSession = new DataCallSession[0];
            saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_GET_MILLIS);
            for (DataCallSession dataCallSession : previousDataCallSession) {
                // sort to de-correlate any potential pattern for UII concern
                Arrays.sort(dataCallSession.handoverFailureCauses);
            }
            return previousDataCallSession;
        } else {
            return null;