Loading proto/src/persist_atoms.proto +1 −1 Original line number Diff line number Diff line Loading @@ -212,7 +212,7 @@ message VoiceCallSession { optional bool video_enabled = 29; optional int32 rat_at_connected = 30; optional bool is_multiparty = 31; optional int32 call_duration = 32; // Internal use only optional int64 setup_begin_millis = 10001; } Loading src/java/com/android/internal/telephony/metrics/MetricsCollector.java +2 −1 Original line number Diff line number Diff line Loading @@ -714,7 +714,8 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { session.mainCodecQuality, session.videoEnabled, session.ratAtConnected, session.isMultiparty); session.isMultiparty, session.callDuration); } private static StatsEvent buildStatsEvent(IncomingSms sms) { Loading src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java +59 −4 Original line number Diff line number Diff line Loading @@ -19,6 +19,13 @@ package com.android.internal.telephony.metrics; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_UNKNOWN; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_FIVE_MINUTES; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_ONE_HOUR; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_ONE_MINUTE; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_TEN_MINUTES; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_THIRTY_MINUTES; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_MORE_THAN_ONE_HOUR; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MO; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MT; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_FULLBAND; Loading Loading @@ -94,6 +101,13 @@ public class VoiceCallSessionStats { private static final int CALL_SETUP_DURATION_ULTRA_SLOW = 10000; // CALL_SETUP_DURATION_EXTREMELY_SLOW has no upper bound (it includes everything above 10000) // Upper bounds of each call duration category in milliseconds. private static final int CALL_DURATION_ONE_MINUTE = 60000; private static final int CALL_DURATION_FIVE_MINUTES = 300000; private static final int CALL_DURATION_TEN_MINUTES = 600000; private static final int CALL_DURATION_THIRTY_MINUTES = 1800000; private static final int CALL_DURATION_ONE_HOUR = 3600000; /** Number of buckets for codec quality, from UNKNOWN to FULLBAND. */ private static final int CODEC_QUALITY_COUNT = 5; Loading @@ -114,6 +128,9 @@ public class VoiceCallSessionStats { /** Holds setup duration buckets with values as their upper bounds in milliseconds. */ private static final SparseIntArray CALL_SETUP_DURATION_MAP = buildCallSetupDurationMap(); /** Holds call duration buckets with values as their upper bounds in milliseconds. */ private static final SparseIntArray CALL_DURATION_MAP = buildCallDurationMap(); /** * Tracks statistics for each call connection, indexed with ID returned by {@link * #getConnectionId}. Loading Loading @@ -189,6 +206,7 @@ public class VoiceCallSessionStats { proto.disconnectReasonCode = conn.getDisconnectCause(); proto.disconnectExtraCode = conn.getPreciseDisconnectCause(); proto.disconnectExtraMessage = conn.getVendorDisconnectCause(); proto.callDuration = classifyCallDuration(conn.getDurationMillis()); finishCall(id); } } Loading Loading @@ -229,19 +247,19 @@ public class VoiceCallSessionStats { List<Integer> imsConnIds = getImsConnectionIds(); if (imsConnIds.size() == 1) { loge("onImsCallTerminated: ending IMS call w/ conn=null"); finishImsCall(imsConnIds.get(0), reasonInfo); finishImsCall(imsConnIds.get(0), reasonInfo, 0); } else { loge("onImsCallTerminated: %d IMS calls w/ conn=null", imsConnIds.size()); } } else { int id = getConnectionId(conn); if (mCallProtos.contains(id)) { finishImsCall(id, reasonInfo); finishImsCall(id, reasonInfo, conn.getDurationMillis()); } else { loge("onImsCallTerminated: untracked connection, connectionId=%d", id); // fake a call so at least some info can be tracked addCall(conn); finishImsCall(id, reasonInfo); finishImsCall(id, reasonInfo, conn.getDurationMillis()); } } } Loading Loading @@ -557,12 +575,13 @@ public class VoiceCallSessionStats { } } private void finishImsCall(int id, ImsReasonInfo reasonInfo) { private void finishImsCall(int id, ImsReasonInfo reasonInfo, long durationMillis) { VoiceCallSession proto = mCallProtos.get(id); proto.bearerAtEnd = VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS; proto.disconnectReasonCode = reasonInfo.mCode; proto.disconnectExtraCode = reasonInfo.mExtraCode; proto.disconnectExtraMessage = ImsStats.filterExtraMessage(reasonInfo.mExtraMessage); proto.callDuration = classifyCallDuration(durationMillis); finishCall(id); } Loading Loading @@ -737,6 +756,19 @@ public class VoiceCallSessionStats { return VOICE_CALL_SESSION__SETUP_DURATION__CALL_SETUP_DURATION_EXTREMELY_SLOW; } private static int classifyCallDuration(long durationMillis) { if (durationMillis == 0L) { return VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN; } // keys in CALL_SETUP_DURATION_MAP are upper bounds in ascending order for (int i = 0; i < CALL_DURATION_MAP.size(); i++) { if (durationMillis < CALL_DURATION_MAP.keyAt(i)) { return CALL_DURATION_MAP.valueAt(i); } } return VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_MORE_THAN_ONE_HOUR; } /** * Generates an ID for each connection, which should be the same for IMS and CS connections * involved in the same SRVCC. Loading Loading @@ -836,4 +868,27 @@ public class VoiceCallSessionStats { return map; } private static SparseIntArray buildCallDurationMap() { SparseIntArray map = new SparseIntArray(); map.put( CALL_DURATION_ONE_MINUTE, VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_ONE_MINUTE); map.put( CALL_DURATION_FIVE_MINUTES, VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_FIVE_MINUTES); map.put( CALL_DURATION_TEN_MINUTES, VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_TEN_MINUTES); map.put( CALL_DURATION_THIRTY_MINUTES, VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_THIRTY_MINUTES); map.put( CALL_DURATION_ONE_HOUR, VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_ONE_HOUR); // anything above would be MORE_THAN_ONE_HOUR return map; } } tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java +31 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,13 @@ package com.android.internal.telephony.metrics; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_FIVE_MINUTES; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_ONE_HOUR; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_ONE_MINUTE; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_TEN_MINUTES; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_THIRTY_MINUTES; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_MORE_THAN_ONE_HOUR; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MO; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MT; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND; Loading Loading @@ -194,6 +201,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE); doReturn(false).when(mImsConnection0).isIncoming(); doReturn(2000L).when(mImsConnection0).getCreateTime(); doReturn(0L).when(mImsConnection0).getDurationMillis(); doReturn(mImsCall0).when(mImsConnection0).getCall(); doReturn(new ArrayList(List.of(mImsConnection0))).when(mImsCall0).getConnections(); VoiceCallSession expectedCall = Loading @@ -211,6 +219,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { expectedCall.mainCodecQuality = VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_SUPER_WIDEBAND; expectedCall.ratAtConnected = TelephonyManager.NETWORK_TYPE_UNKNOWN; expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN; VoiceCallRatUsage expectedRatUsage = makeRatUsageProto( CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 12000L, 1L); Loading Loading @@ -247,6 +256,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE); doReturn(false).when(mImsConnection0).isIncoming(); doReturn(2000L).when(mImsConnection0).getCreateTime(); doReturn(0L).when(mImsConnection0).getDurationMillis(); doReturn(mImsCall0).when(mImsConnection0).getCall(); doReturn(new ArrayList(List.of(mImsConnection0))).when(mImsCall0).getConnections(); VoiceCallSession expectedCall = Loading @@ -257,6 +267,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { ImsReasonInfo.CODE_SIP_FORBIDDEN); expectedCall.setupFailed = true; expectedCall.ratAtConnected = TelephonyManager.NETWORK_TYPE_UNKNOWN; expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN; VoiceCallRatUsage expectedRatUsage = makeRatUsageProto( CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 2200L, 1L); Loading Loading @@ -286,6 +297,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE); doReturn(false).when(mImsConnection0).isIncoming(); 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 = Loading @@ -302,6 +314,8 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { 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_LTE, 2000L, 100000L, 1L); Loading Loading @@ -344,6 +358,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE); doReturn(true).when(mImsConnection0).isIncoming(); doReturn(2000L).when(mImsConnection0).getCreateTime(); doReturn(0L).when(mImsConnection0).getDurationMillis(); doReturn(mImsCall0).when(mImsConnection0).getCall(); doReturn(new ArrayList(List.of(mImsConnection0))).when(mImsCall0).getConnections(); VoiceCallSession expectedCall = Loading @@ -357,6 +372,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { expectedCall.codecBitmask = 1L << AudioCodec.AUDIO_CODEC_AMR; expectedCall.mainCodecQuality = VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND; expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN; VoiceCallRatUsage expectedRatUsage = makeRatUsageProto( CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 8000L, 1L); Loading Loading @@ -390,6 +406,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { doReturn(true).when(mImsConnection0).isIncoming(); doReturn(2000L).when(mImsConnection0).getCreateTime(); doReturn(mImsCall0).when(mImsConnection0).getCall(); doReturn(60006L).when(mImsConnection0).getDurationMillis(); doReturn(new ArrayList(List.of(mImsConnection0))).when(mImsCall0).getConnections(); VoiceCallSession expectedCall = makeSlot0CallProto( Loading @@ -404,6 +421,8 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { expectedCall.codecBitmask = 1L << AudioCodec.AUDIO_CODEC_AMR; expectedCall.mainCodecQuality = VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND; expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_FIVE_MINUTES; VoiceCallRatUsage expectedRatUsage = makeRatUsageProto( CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 12000L, 1L); Loading Loading @@ -658,6 +677,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE); doReturn(true).when(mImsConnection0).isIncoming(); doReturn(2000L).when(mImsConnection0).getCreateTime(); doReturn(300000L).when(mImsConnection0).getDurationMillis(); doReturn(mImsCall0).when(mImsConnection0).getCall(); doReturn(new ArrayList(List.of(mImsConnection0))).when(mImsCall0).getConnections(); VoiceCallSession expectedCall = Loading @@ -674,6 +694,8 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { 1L << AudioCodec.AUDIO_CODEC_AMR | 1L << AudioCodec.AUDIO_CODEC_EVS_SWB; expectedCall.mainCodecQuality = VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND; expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_TEN_MINUTES; mVoiceCallSessionStats0.setTimeMillis(2000L); doReturn(Call.State.INCOMING).when(mImsCall0).getState(); Loading Loading @@ -709,6 +731,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE); doReturn(true).when(mImsConnection0).isIncoming(); doReturn(2000L).when(mImsConnection0).getCreateTime(); doReturn(600001L).when(mImsConnection0).getDurationMillis(); doReturn(mImsCall0).when(mImsConnection0).getCall(); doReturn(new ArrayList(List.of(mImsConnection0))).when(mImsCall0).getConnections(); VoiceCallSession expectedCall = Loading @@ -727,6 +750,8 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { expectedCall.ratSwitchCount = 2L; expectedCall.ratAtEnd = TelephonyManager.NETWORK_TYPE_UMTS; expectedCall.bandAtEnd = 0; expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_THIRTY_MINUTES; VoiceCallRatUsage expectedRatUsageLte = makeRatUsageProto( CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 4000L, 1L); Loading Loading @@ -781,6 +806,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { doReturn(true).when(mImsConnection0).isIncoming(); doReturn(2000L).when(mImsConnection0).getCreateTime(); doReturn(true).when(mImsConnection0).hasRttTextStream(); doReturn(1800001L).when(mImsConnection0).getDurationMillis(); doReturn(mImsCall0).when(mImsConnection0).getCall(); doReturn(new ArrayList(List.of(mImsConnection0))).when(mImsCall0).getConnections(); VoiceCallSession expectedCall = Loading @@ -795,6 +821,8 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { expectedCall.mainCodecQuality = VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND; expectedCall.rttEnabled = true; expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_ONE_HOUR; mVoiceCallSessionStats0.setTimeMillis(2000L); doReturn(Call.State.INCOMING).when(mImsCall0).getState(); Loading Loading @@ -822,6 +850,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { doReturn(true).when(mImsConnection0).isIncoming(); doReturn(2000L).when(mImsConnection0).getCreateTime(); doReturn(mImsCall0).when(mImsConnection0).getCall(); doReturn(3600005L).when(mImsConnection0).getDurationMillis(); doReturn(new ArrayList(List.of(mImsConnection0))).when(mImsCall0).getConnections(); VoiceCallSession expectedCall = makeSlot0CallProto( Loading @@ -837,6 +866,8 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { expectedCall.mainCodecQuality = VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND; expectedCall.rttEnabled = true; expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_MORE_THAN_ONE_HOUR; mVoiceCallSessionStats0.setTimeMillis(2000L); doReturn(Call.State.INCOMING).when(mImsCall0).getState(); Loading Loading
proto/src/persist_atoms.proto +1 −1 Original line number Diff line number Diff line Loading @@ -212,7 +212,7 @@ message VoiceCallSession { optional bool video_enabled = 29; optional int32 rat_at_connected = 30; optional bool is_multiparty = 31; optional int32 call_duration = 32; // Internal use only optional int64 setup_begin_millis = 10001; } Loading
src/java/com/android/internal/telephony/metrics/MetricsCollector.java +2 −1 Original line number Diff line number Diff line Loading @@ -714,7 +714,8 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { session.mainCodecQuality, session.videoEnabled, session.ratAtConnected, session.isMultiparty); session.isMultiparty, session.callDuration); } private static StatsEvent buildStatsEvent(IncomingSms sms) { Loading
src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java +59 −4 Original line number Diff line number Diff line Loading @@ -19,6 +19,13 @@ package com.android.internal.telephony.metrics; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_UNKNOWN; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_FIVE_MINUTES; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_ONE_HOUR; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_ONE_MINUTE; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_TEN_MINUTES; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_THIRTY_MINUTES; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_MORE_THAN_ONE_HOUR; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MO; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MT; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_FULLBAND; Loading Loading @@ -94,6 +101,13 @@ public class VoiceCallSessionStats { private static final int CALL_SETUP_DURATION_ULTRA_SLOW = 10000; // CALL_SETUP_DURATION_EXTREMELY_SLOW has no upper bound (it includes everything above 10000) // Upper bounds of each call duration category in milliseconds. private static final int CALL_DURATION_ONE_MINUTE = 60000; private static final int CALL_DURATION_FIVE_MINUTES = 300000; private static final int CALL_DURATION_TEN_MINUTES = 600000; private static final int CALL_DURATION_THIRTY_MINUTES = 1800000; private static final int CALL_DURATION_ONE_HOUR = 3600000; /** Number of buckets for codec quality, from UNKNOWN to FULLBAND. */ private static final int CODEC_QUALITY_COUNT = 5; Loading @@ -114,6 +128,9 @@ public class VoiceCallSessionStats { /** Holds setup duration buckets with values as their upper bounds in milliseconds. */ private static final SparseIntArray CALL_SETUP_DURATION_MAP = buildCallSetupDurationMap(); /** Holds call duration buckets with values as their upper bounds in milliseconds. */ private static final SparseIntArray CALL_DURATION_MAP = buildCallDurationMap(); /** * Tracks statistics for each call connection, indexed with ID returned by {@link * #getConnectionId}. Loading Loading @@ -189,6 +206,7 @@ public class VoiceCallSessionStats { proto.disconnectReasonCode = conn.getDisconnectCause(); proto.disconnectExtraCode = conn.getPreciseDisconnectCause(); proto.disconnectExtraMessage = conn.getVendorDisconnectCause(); proto.callDuration = classifyCallDuration(conn.getDurationMillis()); finishCall(id); } } Loading Loading @@ -229,19 +247,19 @@ public class VoiceCallSessionStats { List<Integer> imsConnIds = getImsConnectionIds(); if (imsConnIds.size() == 1) { loge("onImsCallTerminated: ending IMS call w/ conn=null"); finishImsCall(imsConnIds.get(0), reasonInfo); finishImsCall(imsConnIds.get(0), reasonInfo, 0); } else { loge("onImsCallTerminated: %d IMS calls w/ conn=null", imsConnIds.size()); } } else { int id = getConnectionId(conn); if (mCallProtos.contains(id)) { finishImsCall(id, reasonInfo); finishImsCall(id, reasonInfo, conn.getDurationMillis()); } else { loge("onImsCallTerminated: untracked connection, connectionId=%d", id); // fake a call so at least some info can be tracked addCall(conn); finishImsCall(id, reasonInfo); finishImsCall(id, reasonInfo, conn.getDurationMillis()); } } } Loading Loading @@ -557,12 +575,13 @@ public class VoiceCallSessionStats { } } private void finishImsCall(int id, ImsReasonInfo reasonInfo) { private void finishImsCall(int id, ImsReasonInfo reasonInfo, long durationMillis) { VoiceCallSession proto = mCallProtos.get(id); proto.bearerAtEnd = VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS; proto.disconnectReasonCode = reasonInfo.mCode; proto.disconnectExtraCode = reasonInfo.mExtraCode; proto.disconnectExtraMessage = ImsStats.filterExtraMessage(reasonInfo.mExtraMessage); proto.callDuration = classifyCallDuration(durationMillis); finishCall(id); } Loading Loading @@ -737,6 +756,19 @@ public class VoiceCallSessionStats { return VOICE_CALL_SESSION__SETUP_DURATION__CALL_SETUP_DURATION_EXTREMELY_SLOW; } private static int classifyCallDuration(long durationMillis) { if (durationMillis == 0L) { return VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN; } // keys in CALL_SETUP_DURATION_MAP are upper bounds in ascending order for (int i = 0; i < CALL_DURATION_MAP.size(); i++) { if (durationMillis < CALL_DURATION_MAP.keyAt(i)) { return CALL_DURATION_MAP.valueAt(i); } } return VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_MORE_THAN_ONE_HOUR; } /** * Generates an ID for each connection, which should be the same for IMS and CS connections * involved in the same SRVCC. Loading Loading @@ -836,4 +868,27 @@ public class VoiceCallSessionStats { return map; } private static SparseIntArray buildCallDurationMap() { SparseIntArray map = new SparseIntArray(); map.put( CALL_DURATION_ONE_MINUTE, VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_ONE_MINUTE); map.put( CALL_DURATION_FIVE_MINUTES, VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_FIVE_MINUTES); map.put( CALL_DURATION_TEN_MINUTES, VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_TEN_MINUTES); map.put( CALL_DURATION_THIRTY_MINUTES, VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_THIRTY_MINUTES); map.put( CALL_DURATION_ONE_HOUR, VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_ONE_HOUR); // anything above would be MORE_THAN_ONE_HOUR return map; } }
tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java +31 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,13 @@ package com.android.internal.telephony.metrics; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_FIVE_MINUTES; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_ONE_HOUR; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_ONE_MINUTE; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_TEN_MINUTES; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_THIRTY_MINUTES; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_MORE_THAN_ONE_HOUR; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MO; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MT; import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND; Loading Loading @@ -194,6 +201,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE); doReturn(false).when(mImsConnection0).isIncoming(); doReturn(2000L).when(mImsConnection0).getCreateTime(); doReturn(0L).when(mImsConnection0).getDurationMillis(); doReturn(mImsCall0).when(mImsConnection0).getCall(); doReturn(new ArrayList(List.of(mImsConnection0))).when(mImsCall0).getConnections(); VoiceCallSession expectedCall = Loading @@ -211,6 +219,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { expectedCall.mainCodecQuality = VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_SUPER_WIDEBAND; expectedCall.ratAtConnected = TelephonyManager.NETWORK_TYPE_UNKNOWN; expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN; VoiceCallRatUsage expectedRatUsage = makeRatUsageProto( CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 12000L, 1L); Loading Loading @@ -247,6 +256,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE); doReturn(false).when(mImsConnection0).isIncoming(); doReturn(2000L).when(mImsConnection0).getCreateTime(); doReturn(0L).when(mImsConnection0).getDurationMillis(); doReturn(mImsCall0).when(mImsConnection0).getCall(); doReturn(new ArrayList(List.of(mImsConnection0))).when(mImsCall0).getConnections(); VoiceCallSession expectedCall = Loading @@ -257,6 +267,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { ImsReasonInfo.CODE_SIP_FORBIDDEN); expectedCall.setupFailed = true; expectedCall.ratAtConnected = TelephonyManager.NETWORK_TYPE_UNKNOWN; expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN; VoiceCallRatUsage expectedRatUsage = makeRatUsageProto( CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 2200L, 1L); Loading Loading @@ -286,6 +297,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE); doReturn(false).when(mImsConnection0).isIncoming(); 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 = Loading @@ -302,6 +314,8 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { 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_LTE, 2000L, 100000L, 1L); Loading Loading @@ -344,6 +358,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE); doReturn(true).when(mImsConnection0).isIncoming(); doReturn(2000L).when(mImsConnection0).getCreateTime(); doReturn(0L).when(mImsConnection0).getDurationMillis(); doReturn(mImsCall0).when(mImsConnection0).getCall(); doReturn(new ArrayList(List.of(mImsConnection0))).when(mImsCall0).getConnections(); VoiceCallSession expectedCall = Loading @@ -357,6 +372,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { expectedCall.codecBitmask = 1L << AudioCodec.AUDIO_CODEC_AMR; expectedCall.mainCodecQuality = VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND; expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN; VoiceCallRatUsage expectedRatUsage = makeRatUsageProto( CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 8000L, 1L); Loading Loading @@ -390,6 +406,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { doReturn(true).when(mImsConnection0).isIncoming(); doReturn(2000L).when(mImsConnection0).getCreateTime(); doReturn(mImsCall0).when(mImsConnection0).getCall(); doReturn(60006L).when(mImsConnection0).getDurationMillis(); doReturn(new ArrayList(List.of(mImsConnection0))).when(mImsCall0).getConnections(); VoiceCallSession expectedCall = makeSlot0CallProto( Loading @@ -404,6 +421,8 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { expectedCall.codecBitmask = 1L << AudioCodec.AUDIO_CODEC_AMR; expectedCall.mainCodecQuality = VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND; expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_FIVE_MINUTES; VoiceCallRatUsage expectedRatUsage = makeRatUsageProto( CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 12000L, 1L); Loading Loading @@ -658,6 +677,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE); doReturn(true).when(mImsConnection0).isIncoming(); doReturn(2000L).when(mImsConnection0).getCreateTime(); doReturn(300000L).when(mImsConnection0).getDurationMillis(); doReturn(mImsCall0).when(mImsConnection0).getCall(); doReturn(new ArrayList(List.of(mImsConnection0))).when(mImsCall0).getConnections(); VoiceCallSession expectedCall = Loading @@ -674,6 +694,8 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { 1L << AudioCodec.AUDIO_CODEC_AMR | 1L << AudioCodec.AUDIO_CODEC_EVS_SWB; expectedCall.mainCodecQuality = VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND; expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_TEN_MINUTES; mVoiceCallSessionStats0.setTimeMillis(2000L); doReturn(Call.State.INCOMING).when(mImsCall0).getState(); Loading Loading @@ -709,6 +731,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE); doReturn(true).when(mImsConnection0).isIncoming(); doReturn(2000L).when(mImsConnection0).getCreateTime(); doReturn(600001L).when(mImsConnection0).getDurationMillis(); doReturn(mImsCall0).when(mImsConnection0).getCall(); doReturn(new ArrayList(List.of(mImsConnection0))).when(mImsCall0).getConnections(); VoiceCallSession expectedCall = Loading @@ -727,6 +750,8 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { expectedCall.ratSwitchCount = 2L; expectedCall.ratAtEnd = TelephonyManager.NETWORK_TYPE_UMTS; expectedCall.bandAtEnd = 0; expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_THIRTY_MINUTES; VoiceCallRatUsage expectedRatUsageLte = makeRatUsageProto( CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 4000L, 1L); Loading Loading @@ -781,6 +806,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { doReturn(true).when(mImsConnection0).isIncoming(); doReturn(2000L).when(mImsConnection0).getCreateTime(); doReturn(true).when(mImsConnection0).hasRttTextStream(); doReturn(1800001L).when(mImsConnection0).getDurationMillis(); doReturn(mImsCall0).when(mImsConnection0).getCall(); doReturn(new ArrayList(List.of(mImsConnection0))).when(mImsCall0).getConnections(); VoiceCallSession expectedCall = Loading @@ -795,6 +821,8 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { expectedCall.mainCodecQuality = VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND; expectedCall.rttEnabled = true; expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_LESS_THAN_ONE_HOUR; mVoiceCallSessionStats0.setTimeMillis(2000L); doReturn(Call.State.INCOMING).when(mImsCall0).getState(); Loading Loading @@ -822,6 +850,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { doReturn(true).when(mImsConnection0).isIncoming(); doReturn(2000L).when(mImsConnection0).getCreateTime(); doReturn(mImsCall0).when(mImsConnection0).getCall(); doReturn(3600005L).when(mImsConnection0).getDurationMillis(); doReturn(new ArrayList(List.of(mImsConnection0))).when(mImsCall0).getConnections(); VoiceCallSession expectedCall = makeSlot0CallProto( Loading @@ -837,6 +866,8 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { expectedCall.mainCodecQuality = VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_NARROWBAND; expectedCall.rttEnabled = true; expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_MORE_THAN_ONE_HOUR; mVoiceCallSessionStats0.setTimeMillis(2000L); doReturn(Call.State.INCOMING).when(mImsCall0).getState(); Loading