Loading proto/src/persist_atoms.proto +1 −0 Original line number Original line Diff line number Diff line Loading @@ -284,6 +284,7 @@ message DataCallSession { optional int64 duration_minutes = 17; optional int64 duration_minutes = 17; optional bool ongoing = 18; optional bool ongoing = 18; optional int32 band_at_end = 19; optional int32 band_at_end = 19; repeated int32 handover_failure_causes = 20; } } message CellularServiceState { message CellularServiceState { Loading src/java/com/android/internal/telephony/data/DataNetwork.java +1 −0 Original line number Original line Diff line number Diff line Loading @@ -2851,6 +2851,7 @@ public class DataNetwork extends StateMachine { mDataNetworkCallback.invokeFromExecutor( mDataNetworkCallback.invokeFromExecutor( () -> mDataNetworkCallback.onHandoverFailed(DataNetwork.this, () -> mDataNetworkCallback.onHandoverFailed(DataNetwork.this, mFailCause, retry, handoverFailureMode)); mFailCause, retry, handoverFailureMode)); mDataCallSessionStats.onHandoverFailure(mFailCause); } } // No matter handover succeeded or not, transit back to connected state. // No matter handover succeeded or not, transit back to connected state. Loading src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java +46 −13 Original line number Original line Diff line number Diff line Loading @@ -44,11 +44,13 @@ import com.android.internal.telephony.SubscriptionController; import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession; import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession; import com.android.telephony.Rlog; import com.android.telephony.Rlog; import java.util.Arrays; import java.util.Random; import java.util.Random; /** Collects data call change events per DataConnection for the pulled atom. */ /** Collects data call change events per DataConnection for the pulled atom. */ public class DataCallSessionStats { public class DataCallSessionStats { private static final String TAG = DataCallSessionStats.class.getSimpleName(); private static final String TAG = DataCallSessionStats.class.getSimpleName(); private static final int SIZE_LIMIT_HANDOVER_FAILURE_CAUSES = 15; private final Phone mPhone; private final Phone mPhone; private long mStartTime; private long mStartTime; Loading Loading @@ -112,12 +114,8 @@ public class DataCallSessionStats { (int) Math.min(response.getRetryDurationMillis(), Integer.MAX_VALUE); (int) Math.min(response.getRetryDurationMillis(), Integer.MAX_VALUE); // If setup has failed, then store the atom // If setup has failed, then store the atom if (failureCause != DataFailCause.NONE) { if (failureCause != DataFailCause.NONE) { mDataCallSession.oosAtEnd = getIsOos(); mDataCallSession.setupFailed = true; mDataCallSession.setupFailed = true; mDataCallSession.ongoing = false; endDataCallSession(); PhoneFactory.getMetricsCollector().unregisterOngoingDataCallStat(this); mAtomsStorage.addDataCallSession(mDataCallSession); mDataCallSession = null; } } } } } } Loading Loading @@ -168,14 +166,28 @@ public class DataCallSessionStats { return; return; } } mDataCallSession.failureCause = failureCause; mDataCallSession.failureCause = failureCause; mDataCallSession.oosAtEnd = getIsOos(); mDataCallSession.ongoing = false; mDataCallSession.durationMinutes = convertMillisToMinutes(getTimeMillis() - mStartTime); mDataCallSession.durationMinutes = convertMillisToMinutes(getTimeMillis() - mStartTime); // store for the data call list event, after DataCall is disconnected and entered into endDataCallSession(); // inactive mode } PhoneFactory.getMetricsCollector().unregisterOngoingDataCallStat(this); mAtomsStorage.addDataCallSession(mDataCallSession); /** mDataCallSession = null; * 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; } } } /** /** Loading @@ -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() { public synchronized void conclude() { if (mDataCallSession != null) { if (mDataCallSession != null) { DataCallSession call = copyOf(mDataCallSession); DataCallSession call = copyOf(mDataCallSession); Loading @@ -207,10 +225,22 @@ public class DataCallSessionStats { call.durationMinutes = convertMillisToMinutes(nowMillis - mStartTime); call.durationMinutes = convertMillisToMinutes(nowMillis - mStartTime); mStartTime = nowMillis; mStartTime = nowMillis; mDataCallSession.ratSwitchCount = 0L; mDataCallSession.ratSwitchCount = 0L; mDataCallSession.handoverFailureCauses = new int[0]; mAtomsStorage.addDataCallSession(call); 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) { private static long convertMillisToMinutes(long millis) { return Math.round(millis / 60000.0); return Math.round(millis / 60000.0); } } Loading @@ -235,6 +265,8 @@ public class DataCallSessionStats { copy.durationMinutes = call.durationMinutes; copy.durationMinutes = call.durationMinutes; copy.ongoing = call.ongoing; copy.ongoing = call.ongoing; copy.bandAtEnd = call.bandAtEnd; copy.bandAtEnd = call.bandAtEnd; copy.handoverFailureCauses = Arrays.copyOf(call.handoverFailureCauses, call.handoverFailureCauses.length); return copy; return copy; } } Loading @@ -257,6 +289,7 @@ public class DataCallSessionStats { proto.deactivateReason = DATA_CALL_SESSION__DEACTIVATE_REASON__DEACTIVATE_REASON_UNKNOWN; proto.deactivateReason = DATA_CALL_SESSION__DEACTIVATE_REASON__DEACTIVATE_REASON_UNKNOWN; proto.durationMinutes = 0; proto.durationMinutes = 0; proto.ongoing = true; proto.ongoing = true; proto.handoverFailureCauses = new int[0]; return proto; return proto; } } Loading src/java/com/android/internal/telephony/metrics/MetricsCollector.java +2 −1 Original line number Original line Diff line number Diff line Loading @@ -811,7 +811,8 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { dataCallSession.deactivateReason, dataCallSession.deactivateReason, round(dataCallSession.durationMinutes, DURATION_BUCKET_MILLIS / MINUTE_IN_MILLIS), round(dataCallSession.durationMinutes, DURATION_BUCKET_MILLIS / MINUTE_IN_MILLIS), dataCallSession.ongoing, dataCallSession.ongoing, dataCallSession.bandAtEnd); dataCallSession.bandAtEnd, dataCallSession.handoverFailureCauses); } } private static StatsEvent buildStatsEvent(ImsRegistrationStats stats) { private static StatsEvent buildStatsEvent(ImsRegistrationStats stats) { Loading src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java +4 −0 Original line number Original line Diff line number Diff line Loading @@ -678,6 +678,10 @@ public class PersistAtomsStorage { DataCallSession[] previousDataCallSession = mAtoms.dataCallSession; DataCallSession[] previousDataCallSession = mAtoms.dataCallSession; mAtoms.dataCallSession = new DataCallSession[0]; mAtoms.dataCallSession = new DataCallSession[0]; saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_GET_MILLIS); 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; return previousDataCallSession; } else { } else { return null; return null; Loading Loading
proto/src/persist_atoms.proto +1 −0 Original line number Original line Diff line number Diff line Loading @@ -284,6 +284,7 @@ message DataCallSession { optional int64 duration_minutes = 17; optional int64 duration_minutes = 17; optional bool ongoing = 18; optional bool ongoing = 18; optional int32 band_at_end = 19; optional int32 band_at_end = 19; repeated int32 handover_failure_causes = 20; } } message CellularServiceState { message CellularServiceState { Loading
src/java/com/android/internal/telephony/data/DataNetwork.java +1 −0 Original line number Original line Diff line number Diff line Loading @@ -2851,6 +2851,7 @@ public class DataNetwork extends StateMachine { mDataNetworkCallback.invokeFromExecutor( mDataNetworkCallback.invokeFromExecutor( () -> mDataNetworkCallback.onHandoverFailed(DataNetwork.this, () -> mDataNetworkCallback.onHandoverFailed(DataNetwork.this, mFailCause, retry, handoverFailureMode)); mFailCause, retry, handoverFailureMode)); mDataCallSessionStats.onHandoverFailure(mFailCause); } } // No matter handover succeeded or not, transit back to connected state. // No matter handover succeeded or not, transit back to connected state. Loading
src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java +46 −13 Original line number Original line Diff line number Diff line Loading @@ -44,11 +44,13 @@ import com.android.internal.telephony.SubscriptionController; import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession; import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession; import com.android.telephony.Rlog; import com.android.telephony.Rlog; import java.util.Arrays; import java.util.Random; import java.util.Random; /** Collects data call change events per DataConnection for the pulled atom. */ /** Collects data call change events per DataConnection for the pulled atom. */ public class DataCallSessionStats { public class DataCallSessionStats { private static final String TAG = DataCallSessionStats.class.getSimpleName(); private static final String TAG = DataCallSessionStats.class.getSimpleName(); private static final int SIZE_LIMIT_HANDOVER_FAILURE_CAUSES = 15; private final Phone mPhone; private final Phone mPhone; private long mStartTime; private long mStartTime; Loading Loading @@ -112,12 +114,8 @@ public class DataCallSessionStats { (int) Math.min(response.getRetryDurationMillis(), Integer.MAX_VALUE); (int) Math.min(response.getRetryDurationMillis(), Integer.MAX_VALUE); // If setup has failed, then store the atom // If setup has failed, then store the atom if (failureCause != DataFailCause.NONE) { if (failureCause != DataFailCause.NONE) { mDataCallSession.oosAtEnd = getIsOos(); mDataCallSession.setupFailed = true; mDataCallSession.setupFailed = true; mDataCallSession.ongoing = false; endDataCallSession(); PhoneFactory.getMetricsCollector().unregisterOngoingDataCallStat(this); mAtomsStorage.addDataCallSession(mDataCallSession); mDataCallSession = null; } } } } } } Loading Loading @@ -168,14 +166,28 @@ public class DataCallSessionStats { return; return; } } mDataCallSession.failureCause = failureCause; mDataCallSession.failureCause = failureCause; mDataCallSession.oosAtEnd = getIsOos(); mDataCallSession.ongoing = false; mDataCallSession.durationMinutes = convertMillisToMinutes(getTimeMillis() - mStartTime); mDataCallSession.durationMinutes = convertMillisToMinutes(getTimeMillis() - mStartTime); // store for the data call list event, after DataCall is disconnected and entered into endDataCallSession(); // inactive mode } PhoneFactory.getMetricsCollector().unregisterOngoingDataCallStat(this); mAtomsStorage.addDataCallSession(mDataCallSession); /** mDataCallSession = null; * 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; } } } /** /** Loading @@ -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() { public synchronized void conclude() { if (mDataCallSession != null) { if (mDataCallSession != null) { DataCallSession call = copyOf(mDataCallSession); DataCallSession call = copyOf(mDataCallSession); Loading @@ -207,10 +225,22 @@ public class DataCallSessionStats { call.durationMinutes = convertMillisToMinutes(nowMillis - mStartTime); call.durationMinutes = convertMillisToMinutes(nowMillis - mStartTime); mStartTime = nowMillis; mStartTime = nowMillis; mDataCallSession.ratSwitchCount = 0L; mDataCallSession.ratSwitchCount = 0L; mDataCallSession.handoverFailureCauses = new int[0]; mAtomsStorage.addDataCallSession(call); 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) { private static long convertMillisToMinutes(long millis) { return Math.round(millis / 60000.0); return Math.round(millis / 60000.0); } } Loading @@ -235,6 +265,8 @@ public class DataCallSessionStats { copy.durationMinutes = call.durationMinutes; copy.durationMinutes = call.durationMinutes; copy.ongoing = call.ongoing; copy.ongoing = call.ongoing; copy.bandAtEnd = call.bandAtEnd; copy.bandAtEnd = call.bandAtEnd; copy.handoverFailureCauses = Arrays.copyOf(call.handoverFailureCauses, call.handoverFailureCauses.length); return copy; return copy; } } Loading @@ -257,6 +289,7 @@ public class DataCallSessionStats { proto.deactivateReason = DATA_CALL_SESSION__DEACTIVATE_REASON__DEACTIVATE_REASON_UNKNOWN; proto.deactivateReason = DATA_CALL_SESSION__DEACTIVATE_REASON__DEACTIVATE_REASON_UNKNOWN; proto.durationMinutes = 0; proto.durationMinutes = 0; proto.ongoing = true; proto.ongoing = true; proto.handoverFailureCauses = new int[0]; return proto; return proto; } } Loading
src/java/com/android/internal/telephony/metrics/MetricsCollector.java +2 −1 Original line number Original line Diff line number Diff line Loading @@ -811,7 +811,8 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { dataCallSession.deactivateReason, dataCallSession.deactivateReason, round(dataCallSession.durationMinutes, DURATION_BUCKET_MILLIS / MINUTE_IN_MILLIS), round(dataCallSession.durationMinutes, DURATION_BUCKET_MILLIS / MINUTE_IN_MILLIS), dataCallSession.ongoing, dataCallSession.ongoing, dataCallSession.bandAtEnd); dataCallSession.bandAtEnd, dataCallSession.handoverFailureCauses); } } private static StatsEvent buildStatsEvent(ImsRegistrationStats stats) { private static StatsEvent buildStatsEvent(ImsRegistrationStats stats) { Loading
src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java +4 −0 Original line number Original line Diff line number Diff line Loading @@ -678,6 +678,10 @@ public class PersistAtomsStorage { DataCallSession[] previousDataCallSession = mAtoms.dataCallSession; DataCallSession[] previousDataCallSession = mAtoms.dataCallSession; mAtoms.dataCallSession = new DataCallSession[0]; mAtoms.dataCallSession = new DataCallSession[0]; saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_GET_MILLIS); 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; return previousDataCallSession; } else { } else { return null; return null; Loading